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.
This commit is contained in:
Marius Gerbershagen 2018-02-18 21:03:07 +01:00
parent 24e4c13d58
commit 7d6112d0e8

View file

@ -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;