From: Ben Maurer Date: Tue, 5 Jul 2005 18:42:42 +0000 (+0000) Subject: 2005-07-05 Ben Maurer X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=607f7c97d5744471cc5cc66f302879b2599debe3;p=gc 2005-07-05 Ben Maurer * pthread_stop_world.c (pthread_start_world, _GC_suspend_handler): Make sure that all threads have been started before releasing the GC_lock. Otherwise, the thread table can be corrupt in the restart handler, causing deadlocks and segfaults. svn path=/trunk/mono/; revision=46962 --- diff --git a/ChangeLog b/ChangeLog index 3393ebea..80702c4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-07-05 Ben Maurer + + * pthread_stop_world.c (pthread_start_world, _GC_suspend_handler): + Make sure that all threads have been started before releasing the + GC_lock. Otherwise, the thread table can be corrupt in the restart + handler, causing deadlocks and segfaults. + 2005-06-22 Zoltan Varga * include/private/gcconfig.h: Fix amd64 build. diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 60a63d5d..68f1dce4 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -163,6 +163,12 @@ static void _GC_suspend_handler(int sig) /* to accidentally leave a RESTART signal pending, thus causing us to */ /* continue prematurely in a future round. */ + /* Tell the thread that wants to start the world that this */ + /* thread has been started. Note that sem_post() is */ + /* the only async-signal-safe primitive in LinuxThreads. */ + sem_post(&GC_suspend_ack_sem); + + #if DEBUG_THREADS GC_printf1("Continuing 0x%lx\n", my_thread); #endif @@ -421,6 +427,7 @@ static void pthread_start_world() register GC_thread p; register int n_live_threads = 0; register int result; + int code; # if DEBUG_THREADS GC_printf0("World starting\n"); @@ -450,6 +457,20 @@ static void pthread_start_world() } } } + + #if DEBUG_THREADS + GC_printf0 ("All threads signaled"); + #endif + + for (i = 0; i < n_live_threads; i++) { + while (0 != (code = sem_wait(&GC_suspend_ack_sem))) { + if (errno != EINTR) { + GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code); + ABORT("sem_wait for handler failed"); + } + } + } + #if DEBUG_THREADS GC_printf0("World started\n"); #endif