aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2018-06-04 14:42:38 +0200
committerSverker Eriksson <[email protected]>2018-06-05 15:58:20 +0200
commit30598c518f793bb7c3893d3996966dca5b858192 (patch)
tree50251942126ce2676dab3e41b83cf18a63fe431e
parent4544915b3b6b9fd9294f4872ea6370d0898e5f2e (diff)
downloadotp-30598c518f793bb7c3893d3996966dca5b858192.tar.gz
otp-30598c518f793bb7c3893d3996966dca5b858192.tar.bz2
otp-30598c518f793bb7c3893d3996966dca5b858192.zip
erts: Fix broken signal queue
broken on master by 613cde66c25464121f2f6dace99782bad0e07d9b Scenario: proc_queue_signal() fails to send switched pending signal due to state & ERTS_PSFLG_FREE, and then calls erts_proc_sig_send_monitor_down() to enqueue to self followed by sig_enqueue_trace_cleanup() that destroyed 'next' pointer of enqueued signal. Solution: Switch order and do sig_enqueue_trace_cleanup() first.
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index e9b41ad298..dc09efa7d7 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -445,6 +445,8 @@ sig_enqueue_trace_cleanup(ErtsMessage *first, ErtsSignal *sig, ErtsMessage *last
case ERTS_SIG_Q_OP_TRACE_CHANGE_STATE:
destroy_trace_info((ErtsSigTraceInfo *) tmp_free);
break;
+ case ERTS_SIG_Q_OP_MONITOR:
+ break; /* ignore flushed pending signal */
default:
ERTS_INTERNAL_ERROR("Unexpected signal op");
break;
@@ -688,19 +690,15 @@ first_last_done:
erts_proc_unlock(rp, ERTS_PROC_LOCK_MSGQ);
if (res == 0) {
+ sig_enqueue_trace_cleanup(first, sig, last);
if (pend_sig) {
if (sig == pend_sig) {
/* We did a switch, callers signal is now pending (still ok) */
ASSERT(esdp->pending_signal.sig);
res = 1;
}
- else {
- ASSERT(first == (ErtsMessage*)pend_sig);
- first = first->next;
- }
erts_proc_sig_send_monitor_down((ErtsMonitor*)pend_sig, am_noproc);
}
- sig_enqueue_trace_cleanup(first, sig, last);
}
erts_proc_notify_new_sig(rp, state, 0);