diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2017-11-17 21:32:40 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2017-11-17 21:32:40 +0300 |
commit | af409e4bdfa25bbab911a706a9f123d98be54c23 (patch) | |
tree | 0d66052d48debef0ba146600942374bc926e4b7e /pthread_stop_world.c | |
parent | 70d0bab7e331ca50d42bab75d85174abab7e1f80 (diff) | |
download | bdwgc-af409e4bdfa25bbab911a706a9f123d98be54c23.tar.gz |
Workaround hangs in sigsuspend and sem_wait if compiled with TSan
Issue #181 (bdwgc).
* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL
&& THREAD_SANITIZER] (GC_suspend_handler_inner): Call
pthread_sigmask(SIG_SETMASK) with an empty set (thus unmask all
signals); add comment.
* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL
&& THREAD_SANITIZER] (GC_stop_world): Call sem_trywait() repeatedly
(with a delay of 100 microseconds) while getting EAGAIN error (instead
of a sem_wait call).
Diffstat (limited to 'pthread_stop_world.c')
-rw-r--r-- | pthread_stop_world.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/pthread_stop_world.c b/pthread_stop_world.c index cfb4c1ae..0f965726 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -310,6 +310,16 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy GC_ATTR_UNUSED, me -> backing_store_ptr = GC_save_regs_in_stack(); # endif +# ifdef THREAD_SANITIZER + /* TSan disables signals around signal handlers. */ + { + sigset_t set; + sigemptyset(&set); + if (pthread_sigmask(SIG_SETMASK, &set, NULL) != 0) + ABORT("pthread_sigmask(SIG_SETMASK) failed"); + } +# 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. */ @@ -827,7 +837,14 @@ GC_INNER void GC_stop_world(void) for (i = 0; i < n_live_threads; i++) { retry: - code = sem_wait(&GC_suspend_ack_sem); +# ifdef THREAD_SANITIZER + /* sem_wait() hangs sometimes. */ + while ((code = sem_trywait(&GC_suspend_ack_sem)) != 0 + && errno == EAGAIN) + usleep(100); +# else + code = sem_wait(&GC_suspend_ack_sem); +# endif if (0 != code) { /* On Linux, sem_wait is documented to always return zero. */ /* But the documentation appears to be incorrect. */ |