From ff5a875bb4ceeffce412a08403dca84ba0a81840 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 28 Dec 2017 11:37:57 +0300 Subject: [PATCH] Prevent multiple sem_post calls for a thread in suspend_handler (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 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pthread_stop_world.c b/pthread_stop_world.c index bda842c..5188cdc 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -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). */ -- 2.7.4