Skip to content

Commit

Permalink
Workaround hangs in sigsuspend and sem_wait if compiled with TSan
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
ivmai committed Nov 17, 2017
1 parent 70d0bab commit af409e4
Showing 1 changed file with 18 additions and 1 deletion.
19 changes: 18 additions & 1 deletion pthread_stop_world.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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. */
Expand Down

0 comments on commit af409e4

Please sign in to comment.