Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Maurer <benm@mono-cvs.ximian.com>2005-07-05 22:42:42 +0400
committerBen Maurer <benm@mono-cvs.ximian.com>2005-07-05 22:42:42 +0400
commita8db23f637fb4bac0524470557977ab6fb811b0f (patch)
tree179b6a253bc6e5082c7b717f52f0c3b447979816 /libgc/pthread_stop_world.c
parent93e98a8f0f1d55ed6acc24f803970c186888ec21 (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.c21
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