Fix removal of dead threads in a child process
authorIvan Maidanski <ivmai@mail.ru>
Tue, 26 Sep 2017 08:01:29 +0000 (11:01 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Sep 2017 08:01:29 +0000 (11:01 +0300)
GC_threads table may contain several elements with the same pthread id,
so GC_remove_all_threads_but_me should remove all elements except for
the first found element matching the id of the current thread.

* pthread_support.c [CAN_HANDLE_FORK] (GC_remove_all_threads_but_me):
Do not assign me if it is already non-null; add comment.
* win32_threads.c [CAN_HANDLE_FORK] (GC_remove_all_threads_but_me):
Likewise.
* win32_threads.c [CAN_HANDLE_FORK] (GC_remove_all_threads_but_me):
Remove GC_ASSERT(me==NULL).

pthread_support.c
win32_threads.c

index 379848c..2694ec8 100644 (file)
@@ -754,7 +754,8 @@ STATIC void GC_remove_all_threads_but_me(void)
       me = 0;
       for (p = GC_threads[hv]; 0 != p; p = next) {
         next = p -> next;
-        if (THREAD_EQUAL(p -> id, self)) {
+        if (THREAD_EQUAL(p -> id, self)
+            && me == NULL) { /* ignore dead threads with the same id */
           me = p;
           p -> next = 0;
 #         ifdef GC_DARWIN_THREADS
index 24f16db..18acb57 100644 (file)
@@ -1031,8 +1031,8 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn,
       for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
         for (p = GC_threads[hv]; 0 != p; p = next) {
           next = p -> tm.next;
-          if (THREAD_EQUAL(p -> pthread_id, pthread_id)) {
-            GC_ASSERT(me == NULL);
+          if (THREAD_EQUAL(p -> pthread_id, pthread_id)
+              && me == NULL) { /* ignore dead threads with the same id */
             me = p;
             p -> tm.next = 0;
           } else {