aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2018-05-21 07:45:55 +0200
committerJohn Högberg <[email protected]>2018-06-14 08:25:41 +0200
commit4013f4840d8d540c63fa7901c2d8d1653ae45821 (patch)
tree3d934e2bf2c653f5961fa57ee778e527fe3e8e1a /erts
parent254c4a5615d7bf52acec02437fab8c771fc46a8f (diff)
downloadotp-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')
-rw-r--r--erts/emulator/beam/erl_process.c9
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;