Make recursion_check work for multiple threads
authorJanne Blomqvist <jb@gcc.gnu.org>
Fri, 23 Nov 2018 20:42:03 +0000 (22:42 +0200)
committerJanne Blomqvist <jb@gcc.gnu.org>
Fri, 23 Nov 2018 20:42:03 +0000 (22:42 +0200)
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

libgfortran/ChangeLog
libgfortran/runtime/error.c

index 59c16f35072e2870269f685982e8b703a8ddf436..d9397623ee1a4dd3c1d1c74ecd0f482b19c2d262 100644 (file)
@@ -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
index b07a4c0b12a57e93ee4546c074cfc2b081f49e5d..7c52733c19c56983596f8a5a69a7eb2279720aa5 100644 (file)
@@ -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