From f0506f511e23e7d4a2471f6cc0530f2f006f5e1a Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Sat, 17 Feb 2018 16:24:38 +0100 Subject: [PATCH] threading: fix possible race conditions in ecl_wakeup_waiters Checking process.phase without holding the start_stop_spinlock looks dangerous, the thread may exit after the check but before we interrupt it. Also, we can't call mp_process_kill while interrupts are disabled, so we have to use the lower level ecl_interrupt_process. --- src/c/threads/queue.d | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/c/threads/queue.d b/src/c/threads/queue.d index 64e45495c..9c2523053 100755 --- a/src/c/threads/queue.d +++ b/src/c/threads/queue.d @@ -338,6 +338,7 @@ ecl_wakeup_waiters(cl_env_ptr the_env, cl_object q, int flags) cl_object *tail, l; for (tail = &q->queue.list; (l = *tail) != ECL_NIL; ) { cl_object p = ECL_CONS_CAR(l); + ecl_get_spinlock(the_env, &p->process.start_stop_spinlock); if (p->process.phase == ECL_PROCESS_INACTIVE || p->process.phase == ECL_PROCESS_EXITING) { print_lock("removing %p", q, p); @@ -351,12 +352,15 @@ ecl_wakeup_waiters(cl_env_ptr the_env, cl_object q, int flags) *tail = ECL_CONS_CDR(l); tail = &ECL_CONS_CDR(l); if (flags & ECL_WAKEUP_KILL) - mp_process_kill(p); + ecl_interrupt_process(p, @'mp::exit-process'); else ecl_wakeup_process(p); - if (!(flags & ECL_WAKEUP_ALL)) + if (!(flags & ECL_WAKEUP_ALL)) { + ecl_giveup_spinlock(&p->process.start_stop_spinlock); break; + } } + ecl_giveup_spinlock(&p->process.start_stop_spinlock); } } ecl_giveup_spinlock(&q->queue.spinlock);