Prevent multiple sem_post calls for a thread in suspend_handler
authorIvan Maidanski <ivmai@mail.ru>
Thu, 28 Dec 2017 08:37:57 +0000 (11:37 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 28 Dec 2017 08:37:57 +0000 (11:37 +0300)
(fix commit af409e4bd)

Issue #181 (bdwgc).

* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL
&& THREAD_SANITIZER] (GC_suspend_handler_inner): Call pthread_sigmask()
after last_stop_count update (thus preventing duplicate sem_post() call
in case of GC_suspend_handler_inner is re-entered (if GC_retry_signals);
refine comment.

pthread_stop_world.c

index bda842c..5188cdc 100644 (file)
@@ -333,8 +333,15 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy GC_ATTR_UNUSED,
   }
   GC_store_stack_ptr(me);
 
+  /* Tell the thread that wants to stop the world that this     */
+  /* thread has been stopped.  Note that sem_post() is          */
+  /* the only async-signal-safe primitive in LinuxThreads.      */
+  sem_post(&GC_suspend_ack_sem);
+  AO_store_release(&me->stop_info.last_stop_count, my_stop_count);
+
 # ifdef THREAD_SANITIZER
-    /* TSan disables signals around signal handlers.    */
+    /* TSan disables signals around signal handlers.  Without   */
+    /* a pthread_sigmask call, sigsuspend may block forever.    */
     {
       sigset_t set;
       sigemptyset(&set);
@@ -343,12 +350,6 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy GC_ATTR_UNUSED,
     }
 # endif
 
-  /* Tell the thread that wants to stop the world that this     */
-  /* thread has been stopped.  Note that sem_post() is          */
-  /* the only async-signal-safe primitive in LinuxThreads.      */
-  sem_post(&GC_suspend_ack_sem);
-  AO_store_release(&me->stop_info.last_stop_count, my_stop_count);
-
   /* Wait until that thread tells us to restart by sending      */
   /* this thread a GC_sig_thr_restart signal (should be masked  */
   /* at this point thus there is no race).                      */