From d4ac047bf12c75d74c69627750728273ca5b02bf Mon Sep 17 00:00:00 2001 From: jb Date: Fri, 23 Nov 2018 20:42:03 +0000 Subject: [PATCH] Make recursion_check work for multiple threads With multiple threads, using an unprotected static variable to check whether recursion has occured isn't valid, as one thread might have modified the variable, thus causing another thread to incorrectly conclude that recursion has occured. This patch avoids this problem by using a thread-specific variable for the recursion check. Regtested on x86_64-pc-linux-gnu. libgfortran/ChangeLog: 2018-11-23 Janne Blomqvist * runtime/error.c (MAGIC): Remove. (recursion_key): New variable. (recursion_check): Use thread-specific variable for recursion check if threads are active. (constructor_recursion_check): New function. (destructor_recursion_check): New funcion. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@266419 138bc75d-0d04-0410-961f-82ee72b054a4 --- libgfortran/ChangeLog | 9 ++++++++ libgfortran/runtime/error.c | 43 +++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 59c16f35072e..d9397623ee1a 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,12 @@ +2018-11-23 Janne Blomqvist + + * runtime/error.c (MAGIC): Remove. + (recursion_key): New variable. + (recursion_check): Use thread-specific variable for recursion + check if threads are active. + (constructor_recursion_check): New function. + (destructor_recursion_check): New funcion. + 2018-11-22 Janne Blomqvist * acinclude.m4 (LIBGFOR_CHECK_ATOMIC_FETCH_ADD): Rename and test diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c index b07a4c0b12a5..7c52733c19c5 100644 --- a/libgfortran/runtime/error.c +++ b/libgfortran/runtime/error.c @@ -332,21 +332,50 @@ show_locus (st_parameter_common *cmp) /* recursion_check()-- It's possible for additional errors to occur * during fatal error processing. We detect this condition here and - * exit with code 4 immediately. */ + * abort immediately. */ -#define MAGIC 0x20DE8101 +static __gthread_key_t recursion_key; static void recursion_check (void) { - static int magic = 0; + if (__gthread_active_p ()) + { + bool* p = __gthread_getspecific (recursion_key); + if (!p) + { + p = xcalloc (1, sizeof (bool)); + __gthread_setspecific (recursion_key, p); + } + if (*p) + sys_abort (); + *p = true; + } + else + { + static bool recur; + if (recur) + sys_abort (); + recur = true; + } +} - /* Don't even try to print something at this point */ - if (magic == MAGIC) - sys_abort (); +#ifdef __GTHREADS +static void __attribute__((constructor)) +constructor_recursion_check (void) +{ + if (__gthread_active_p ()) + __gthread_key_create (&recursion_key, &free); +} - magic = MAGIC; +static void __attribute__((destructor)) +destructor_recursion_check (void) +{ + if (__gthread_active_p ()) + __gthread_key_delete (recursion_key); } +#endif + #define STRERR_MAXSZ 256 -- 2.47.2