]> granicus.if.org Git - gc/commitdiff
Workaround a hang in sigsuspend if compiled with Thread Sanitizer
authorIvan Maidanski <ivmai@mail.ru>
Mon, 13 Nov 2017 06:04:04 +0000 (09:04 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Mon, 13 Nov 2017 06:04:04 +0000 (09:04 +0300)
Issue #181 (bdwgc).

* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL
&& THREAD_SANITIZER] (GC_suspend_handler_inner): Use sched_yield()
instead of sigsuspend(&suspend_handler_mask); add TODO item.

pthread_stop_world.c

index cfb4c1ae85884646abc7b731a368e0339aa73154..b30b9e16a00df1ae3316b528f009ca9ba2ce5b97 100644 (file)
@@ -327,7 +327,16 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy GC_ATTR_UNUSED,
   /* really safe to proceed.  Under normal circumstances,       */
   /* this code should not be executed.                          */
   do {
+#   ifdef THREAD_SANITIZER
+      /* TODO: A temporal workaround.  Generally, signal handlers are   */
+      /* delayed until the next call to TSan ProcessPendingSignals, the */
+      /* latter is called on interceptors, system calls, and atomic     */
+      /* operations only.  Thus, the collector hangs sometimes (as of   */
+      /* now) if the signal occurs while waiting in sigsuspend().       */
+      sched_yield();
+#   else
       sigsuspend (&suspend_handler_mask);
+#   endif
   } while (AO_load_acquire(&GC_world_is_stopped)
            && AO_load(&GC_stop_count) == my_stop_count);
   /* If the RESTART signal gets lost, we can still lose.  That should   */