From 7d6112d0e8d5f712f867dee5bb379a032649f09e Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Sun, 18 Feb 2018 21:03:07 +0100 Subject: [PATCH] threading: fix race condition in pop_signal The pending interrupts list may be modified after we have checked whether it is nil, but before we aquire the spinlock, leading to segmentation faults. --- src/c/unixint.d | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/c/unixint.d b/src/c/unixint.d index f372b7cc3..84fba451c 100644 --- a/src/c/unixint.d +++ b/src/c/unixint.d @@ -422,17 +422,18 @@ static cl_object pop_signal(cl_env_ptr env) { cl_object record, value; - if (env->interrupt_struct->pending_interrupt == ECL_NIL) { - return ECL_NIL; - } ECL_WITH_SPINLOCK_BEGIN(env, &env->interrupt_struct->signal_queue_spinlock) { - record = env->interrupt_struct->pending_interrupt; - value = ECL_CONS_CAR(record); - env->interrupt_struct->pending_interrupt = ECL_CONS_CDR(record); - /* Save some conses for future use, to avoid allocating */ - if (ECL_SYMBOLP(value) || ECL_FIXNUMP(value)) { - ECL_RPLACD(record, env->interrupt_struct->signal_queue); - env->interrupt_struct->signal_queue = record; + if (env->interrupt_struct->pending_interrupt == ECL_NIL) { + value = ECL_NIL; + } else { + record = env->interrupt_struct->pending_interrupt; + value = ECL_CONS_CAR(record); + env->interrupt_struct->pending_interrupt = ECL_CONS_CDR(record); + /* Save some conses for future use, to avoid allocating */ + if (ECL_SYMBOLP(value) || ECL_FIXNUMP(value)) { + ECL_RPLACD(record, env->interrupt_struct->signal_queue); + env->interrupt_struct->signal_queue = record; + } } } ECL_WITH_SPINLOCK_END; return value;