diff options
author | Ben Maurer <benm@mono-cvs.ximian.com> | 2005-07-05 22:42:42 +0400 |
---|---|---|
committer | Ben Maurer <benm@mono-cvs.ximian.com> | 2005-07-05 22:42:42 +0400 |
commit | a8db23f637fb4bac0524470557977ab6fb811b0f (patch) | |
tree | 179b6a253bc6e5082c7b717f52f0c3b447979816 /libgc/pthread_stop_world.c | |
parent | 93e98a8f0f1d55ed6acc24f803970c186888ec21 (diff) |
2005-07-05 Ben Maurer <bmaurer@ximian.com>
* 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
Diffstat (limited to 'libgc/pthread_stop_world.c')
-rw-r--r-- | libgc/pthread_stop_world.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c index 60a63d5d8ac..68f1dce4306 100644 --- a/libgc/pthread_stop_world.c +++ b/libgc/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 |