diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 59c16f35072..d9397623ee1 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 b07a4c0b12a..7c52733c19c 100644 --- a/libgfortran/runtime/error.c +++ b/libgfortran/runtime/error.c @@ -332,22 +332,51 @@ 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; - - /* Don't even try to print something at this point */ - if (magic == MAGIC) - sys_abort (); - - magic = MAGIC; + 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; + } } +#ifdef __GTHREADS +static void __attribute__((constructor)) +constructor_recursion_check (void) +{ + if (__gthread_active_p ()) + __gthread_key_create (&recursion_key, &free); +} + +static void __attribute__((destructor)) +destructor_recursion_check (void) +{ + if (__gthread_active_p ()) + __gthread_key_delete (recursion_key); +} +#endif + + #define STRERR_MAXSZ 256