From a8d7305fb6c3087d074ccabb1a174d72b3b5f3f9 Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Tue, 20 Feb 2018 21:40:04 +0100 Subject: [PATCH] threading: fix race condition in stacks_scanner The garbage collector can call stacks_scanner in a thread before pthread_setspecific, leading to a wrong error message. The solution is simply not to mark the environment, if pthread_setspecific has not yet been called. --- src/c/alloc_2.d | 2 +- src/c/threads/process.d | 10 ++++++++++ src/h/external.h | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/c/alloc_2.d b/src/c/alloc_2.d index ef5a0fd1e..f749abcf4 100644 --- a/src/c/alloc_2.d +++ b/src/c/alloc_2.d @@ -1353,7 +1353,7 @@ ecl_mark_env(struct cl_env_struct *env) static void stacks_scanner() { - cl_env_ptr the_env = ecl_process_env(); + cl_env_ptr the_env = ecl_process_env_unsafe(); cl_object l; l = cl_core.libraries; if (l) { diff --git a/src/c/threads/process.d b/src/c/threads/process.d index ff8620648..3429057cf 100755 --- a/src/c/threads/process.d +++ b/src/c/threads/process.d @@ -43,6 +43,16 @@ static pthread_key_t cl_env_key; extern void ecl_init_env(struct cl_env_struct *env); #if !defined(WITH___THREAD) +cl_env_ptr +ecl_process_env_unsafe(void) +{ +#ifdef ECL_WINDOWS_THREADS + return TlsGetValue(cl_env_key); +#else + return pthread_getspecific(cl_env_key); +#endif +} + cl_env_ptr ecl_process_env(void) { diff --git a/src/h/external.h b/src/h/external.h index 2aa236962..c5c29f7c5 100755 --- a/src/h/external.h +++ b/src/h/external.h @@ -161,14 +161,17 @@ struct ecl_interrupt_struct { # ifdef WITH___THREAD # define cl_env (*cl_env_p) # define ecl_process_env() cl_env_p +# define ecl_process_env_unsafe() cl_env_p extern __thread cl_env_ptr cl_env_p; # else # define cl_env (*ecl_process_env()) extern ECL_API cl_env_ptr ecl_process_env(void) __attribute__((const)); + extern ECL_API cl_env_ptr ecl_process_env_unsafe(void) __attribute__((const)); # endif #else # define cl_env (*cl_env_p) # define ecl_process_env() cl_env_p +# define ecl_process_env_unsafe() cl_env_p extern ECL_API cl_env_ptr cl_env_p; #endif