From 276f4c79ff65480aac120b5ddd6e6ece706b6f64 Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Sun, 4 Feb 2018 21:26:08 +0100 Subject: [PATCH] threading: save/restore more environment elements in handle_all_queued to prevent race conditions env->stack_top has to be temporarily increased too, to prevent it from being overwritten from the interrupting code. --- src/c/unixint.d | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/c/unixint.d b/src/c/unixint.d index b1516c563..497abd440 100644 --- a/src/c/unixint.d +++ b/src/c/unixint.d @@ -367,13 +367,23 @@ si_handle_signal(cl_object signal_code, cl_object process) static void handle_all_queued(cl_env_ptr env) { - /* We have to save and later restore env->function for the - * case that we get interrupted directly after - * ecl_function_dispatch */ + /* We have to save and later restore env->function, + * env->nvalues and env->values to ensure that they don't get + * overwritten by the interrupting code */ cl_object fun = env->function; + cl_index nvalues = env->nvalues; + cl_object values[ECL_MULTIPLE_VALUES_LIMIT]; + memcpy(values, env->values, ECL_MULTIPLE_VALUES_LIMIT*sizeof(cl_object)); + /* We might have been interrupted while we push/pop in the + * stack. Increasing env->stack_top ensures that we don't + * overwrite the topmost stack value. */ + env->stack_top++; while (env->interrupt_struct->pending_interrupt != ECL_NIL) { handle_signal_now(pop_signal(env), env->own_process); } + env->stack_top--; + memcpy(env->values, values, ECL_MULTIPLE_VALUES_LIMIT*sizeof(cl_object)); + env->nvalues = nvalues; env->function = fun; }