aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2018-06-11 15:56:59 +0200
committerSverker Eriksson <[email protected]>2018-06-11 15:56:59 +0200
commitc5a6b03c9ee71bb13723f6ca6ff0e8f6cd16fe24 (patch)
tree13299509de8753b723a20139b102039d7e914659
parent463c8e7fa08388f138fd9f07995d7c7a7580507e (diff)
downloadotp-c5a6b03c9ee71bb13723f6ca6ff0e8f6cd16fe24.tar.gz
otp-c5a6b03c9ee71bb13723f6ca6ff0e8f6cd16fe24.tar.bz2
otp-c5a6b03c9ee71bb13723f6ca6ff0e8f6cd16fe24.zip
erts: Fix incoming signal handling for exiting process
Seen symptom: handle_process_info() called with is_alive=1 on exiting process, reading broken Process.u.initial.module atom overwritten by Process.u.terminate pointer. Solution: Let erts_proc_sig_handle_incoming() do nothing if process is already exiting.
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index 1aa390d94d..d6d22677e7 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -2723,6 +2723,9 @@ handle_process_info(Process *c_p, ErtsSigRecvTracing *tracing,
Uint reds = 0;
Process *rp;
+ ASSERT(!!is_alive == !(erts_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_EXITING));
+
if (pisig->msgq_len_offset != ERTS_PROC_SIG_PI_MSGQ_LEN_IGNORE) {
/*
* Request requires message queue data to be updated
@@ -3007,10 +3010,8 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
- if (local_only)
- state = -1; /* can never be a valid state... */
- else {
- state = erts_atomic32_read_nob(&c_p->state);
+ state = erts_atomic32_read_nob(&c_p->state);
+ if (!local_only) {
if (ERTS_PSFLG_SIG_IN_Q & state) {
erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
erts_proc_sig_fetch(c_p);
@@ -3023,13 +3024,15 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
yield = 0;
if (!c_p->sig_qs.cont) {
- if (state == -1)
- *statep = erts_atomic32_read_nob(&c_p->state);
- else
- *statep = state;
+ *statep = state;
return !0;
}
+ if (state & ERTS_PSFLG_EXITING) {
+ *statep = state;
+ return 0;
+ }
+
next_nm_sig = &c_p->sig_qs.nmsigs.next;
setup_tracing_state(c_p, &tracing);