diff options
author | Sverker Eriksson <[email protected]> | 2018-06-04 14:42:38 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2018-06-05 15:58:20 +0200 |
commit | 30598c518f793bb7c3893d3996966dca5b858192 (patch) | |
tree | 50251942126ce2676dab3e41b83cf18a63fe431e | |
parent | 4544915b3b6b9fd9294f4872ea6370d0898e5f2e (diff) | |
download | otp-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.c | 8 |
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); |