]> granicus.if.org Git - gc/commitdiff
Fix GC_remove_all_threads_but_me for fork-unfriendly TLS implementations
authorIvan Maidanski <ivmai@mail.ru>
Sun, 26 Feb 2012 15:36:11 +0000 (19:36 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 26 Feb 2012 15:36:11 +0000 (19:36 +0400)
* pthread_support.c (GC_remove_all_threads_but_me): Refine comment for
stop_info.mach_thread update.
* pthread_support.c (GC_remove_all_threads_but_me): Call
GC_setspecific (if THREAD_LOCAL_ALLOC) to re-assign thread-local
pointer to 'tlfs' (identified by GC_thread_key) of the current thread
(except for USE_CUSTOM_SPECIFIC).

pthread_support.c

index e1bfc945fd88ca9528e4882b7d915798a4fed1b4..3e6285880335cd4a019d2768d991a01169cf320e 100644 (file)
@@ -664,8 +664,18 @@ STATIC void GC_remove_all_threads_but_me(void)
           me = p;
           p -> next = 0;
 #         ifdef GC_DARWIN_THREADS
-            /* Update thread Id after fork. */
+            /* Update thread Id after fork (it is ok to call    */
+            /* GC_destroy_thread_local and GC_free_internal     */
+            /* before update).                                  */
             me -> stop_info.mach_thread = mach_thread_self();
+#         endif
+#         if defined(THREAD_LOCAL_ALLOC) && !defined(USE_CUSTOM_SPECIFIC)
+            /* Some TLS implementations might be not fork-friendly, so  */
+            /* we re-assign thread-local pointer to 'tlfs' for safety   */
+            /* instead of the assertion check (again, it is ok to call  */
+            /* GC_destroy_thread_local and GC_free_internal before).    */
+            if (GC_setspecific(GC_thread_key, &me->tlfs) != 0)
+              ABORT("GC_setspecific failed (in child)");
 #         endif
         } else {
 #         ifdef THREAD_LOCAL_ALLOC