diff options
author | Sverker Eriksson <sverker@erlang.org> | 2016-04-01 20:11:34 +0200 |
---|---|---|
committer | Sverker Eriksson <sverker@erlang.org> | 2016-04-01 20:11:34 +0200 |
commit | c048886458ce68280ba32647a93a04902c929988 (patch) | |
tree | 0f61bf30bef3049ebff71b9e566c256b7d07efd7 /erts | |
parent | 6d4001de141a00b3bf37b8f7b24c5bde2b4f4015 (diff) | |
download | erlang-c048886458ce68280ba32647a93a04902c929988.tar.gz |
erts: Fix race for process_flag(trap_exit,true)
and a concurrent exit signal.
We now actually guarantee that the process will not die
from exit signal *after* the call to process_flag(trap_exit,true)
has returned.
The race is narrow and probably quite hard to observe even if you
manage to provoke it. Has only been confirmed with the help of
return trace and a sleep in send_exit_signal().
Solution:
Seize status lock to prevent send_exit_signal() from reading
an old status (without TRAP_EXIT) and then writing PENDING_EXIT
after TRAP_EXIT has been set by process_flag_2().
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/bif.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index b43137597e..11c694233f 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -1566,14 +1566,17 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2) * true. For more info, see implementation of * erts_send_exit_signal(). */ + erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCKS_XSIG_SEND); if (trap_exit) state = erts_smp_atomic32_read_bor_mb(&BIF_P->state, ERTS_PSFLG_TRAP_EXIT); else state = erts_smp_atomic32_read_band_mb(&BIF_P->state, ~ERTS_PSFLG_TRAP_EXIT); + erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_XSIG_SEND); + #ifdef ERTS_SMP - if (ERTS_PROC_PENDING_EXIT(BIF_P)) { + if (state & ERTS_PSFLG_PENDING_EXIT) { erts_handle_pending_exit(BIF_P, ERTS_PROC_LOCK_MAIN); ERTS_BIF_EXITED(BIF_P); } |