diff options
author | John Högberg <[email protected]> | 2018-05-21 07:45:55 +0200 |
---|---|---|
committer | John Högberg <[email protected]> | 2018-06-14 08:25:41 +0200 |
commit | 4013f4840d8d540c63fa7901c2d8d1653ae45821 (patch) | |
tree | 3d934e2bf2c653f5961fa57ee778e527fe3e8e1a /erts/emulator/beam | |
parent | 254c4a5615d7bf52acec02437fab8c771fc46a8f (diff) | |
download | otp-4013f4840d8d540c63fa7901c2d8d1653ae45821.tar.gz otp-4013f4840d8d540c63fa7901c2d8d1653ae45821.tar.bz2 otp-4013f4840d8d540c63fa7901c2d8d1653ae45821.zip |
Fix erroneous schedule of freed/exiting processes
When scheduled out, the process was never checked for the FREE state
before rescheduling, which meant that a system task could sneak in
and cause a double-free later on.
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/erl_process.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index ee6d56b5d7..b0db2da243 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -6900,8 +6900,9 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p, enqueue = ERTS_ENQUEUE_NOT; n &= ~running_flgs; - if ((a & (ERTS_PSFLG_ACTIVE_SYS|ERTS_PSFLG_DIRTY_ACTIVE_SYS)) - || (a & (ERTS_PSFLG_ACTIVE|ERTS_PSFLG_SUSPENDED)) == ERTS_PSFLG_ACTIVE) { + if ((!!(a & (ERTS_PSFLG_ACTIVE_SYS|ERTS_PSFLG_DIRTY_ACTIVE_SYS)) + | ((a & (ERTS_PSFLG_ACTIVE|ERTS_PSFLG_SUSPENDED)) == ERTS_PSFLG_ACTIVE)) + & !(a & ERTS_PSFLG_FREE)) { enqueue = check_enqueue_in_prio_queue(p, &enq_prio, &n, a); } a = erts_smp_atomic32_cmpxchg_mb(&p->state, n, e); @@ -14069,7 +14070,9 @@ erts_continue_exit_process(Process *p) n = e = a; ASSERT(a & ERTS_PSFLG_EXITING); n |= ERTS_PSFLG_FREE; - n &= ~ERTS_PSFLG_ACTIVE; + n &= ~(ERTS_PSFLG_ACTIVE + | ERTS_PSFLG_ACTIVE_SYS + | ERTS_PSFLG_DIRTY_ACTIVE_SYS); if ((n & ERTS_PSFLG_IN_RUNQ) && !refc_inced) { erts_proc_inc_refc(p); refc_inced = 1; |