aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2018-11-23 22:42:03 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2018-11-23 22:42:03 +0200
commitf4c0f888817ee7c593b56a5fe47b4acfbc83c7d3 (patch)
tree4ab252c7af94ffd81381887e7c0c7777d36818c4
parent70c70369ce868fd8b049f710c01a899e502f6f68 (diff)
downloadgcc-f4c0f888817ee7c593b56a5fe47b4acfbc83c7d3.zip
gcc-f4c0f888817ee7c593b56a5fe47b4acfbc83c7d3.tar.gz
gcc-f4c0f888817ee7c593b56a5fe47b4acfbc83c7d3.tar.bz2
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 <jb@gcc.gnu.org> * 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. From-SVN: r266419
-rw-r--r--libgfortran/ChangeLog9
-rw-r--r--libgfortran/runtime/error.c43
2 files changed, 45 insertions, 7 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 59c16f3..d939762 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,12 @@
+2018-11-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * 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 <jb@gcc.gnu.org>
* acinclude.m4 (LIBGFOR_CHECK_ATOMIC_FETCH_ADD): Rename and test
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index b07a4c0..7c52733 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