]> granicus.if.org Git - gc/commitdiff
Fix fork() handling for Darwin partially
authorIvan Maidanski <ivmai@mail.ru>
Fri, 24 Feb 2012 07:29:48 +0000 (11:29 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Fri, 24 Feb 2012 07:29:48 +0000 (11:29 +0400)
(still not handled well for Darwin if GC incremental mode is on)

* os_dep.c (GC_dirty_init): Add FIXME regarding fork (Darwin).
* pthread_support.c (GC_remove_all_threads_but_me): Update mach_thread
for "me" (Darwin).
* pthread_support.c (GC_fork_prepare_proc): Output warning if
GC_dirty_maintained (if DARWIN and MPROTECT_VDB).
* pthread_support.c (GC_fork_prepare_proc, GC_fork_child_proc): Add
FIXME (for Darwin).
* tests/test.c (run_one_test): Do not test fork() for Darwin with
incremental mode on (if HANDLE_FORK); add FIXME.

os_dep.c
pthread_support.c
tests/test.c

index 00467675be70f110449ddf9fc35f391841902910..6a15816f371640d62c2207682f7cfca905ff9cec 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -4161,6 +4161,10 @@ GC_INNER void GC_dirty_init(void)
   if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
     ABORT("pthread_attr_setdetachedstate failed");
 
+# if defined(HANDLE_FORK) && !defined(THREADS)
+    /* FIXME: See comment in GC_fork_prepare_proc.      */
+# endif
+
 # undef pthread_create
   /* This will call the real pthread function, not our wrapper */
   if (pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
index 9a9c9d34d8f0441a12181af1f237f8a5565e1df7..e43f20a0856a9f280a0a16d7324d92c6d6662c39 100644 (file)
@@ -663,6 +663,10 @@ STATIC void GC_remove_all_threads_but_me(void)
         if (THREAD_EQUAL(p -> id, self)) {
           me = p;
           p -> next = 0;
+#         ifdef GC_DARWIN_THREADS
+            /* Update thread Id after fork. */
+            me -> stop_info.mach_thread = mach_thread_self();
+#         endif
         } else {
 #         ifdef THREAD_LOCAL_ALLOC
             if (!(p -> flags & FINISHED)) {
@@ -918,6 +922,14 @@ STATIC void GC_fork_prepare_proc(void)
     /* Wait for an ongoing GC to finish, since we can't finish it in    */
     /* the (one remaining thread in) the child.                         */
       LOCK();
+#     if defined(GC_DARWIN_THREADS) && defined(MPROTECT_VDB)
+        if (GC_dirty_maintained) {
+          WARN("GC incremental mode is incompatible with fork() for now\n", 0);
+          /* Currently, it is not allowed to use any GC allocated data  */
+          /* or call any GC function in the child (before exec).        */
+          /* FIXME: Remove warning when mode implemented in child_proc. */
+        }
+#     endif
       DISABLE_CANCEL(fork_cancel_state);
                 /* Following waits may include cancellation points. */
 #     if defined(PARALLEL_MARK)
@@ -949,6 +961,11 @@ STATIC void GC_fork_child_proc(void)
 #   if defined(PARALLEL_MARK)
       if (GC_parallel)
         GC_release_mark_lock();
+#   endif
+#   if defined(GC_DARWIN_THREADS) && defined(MPROTECT_VDB)
+      /* FIXME: Since GC_mprotect_thread is not running in the child,   */
+      /* GC_dirty_maintained should be switched off gracefully          */
+      /* (unprotecting all pages and clearing GC_mach_handler_thread).  */
 #   endif
     GC_remove_all_threads_but_me();
 #   ifdef PARALLEL_MARK
index e2134526b89fdf18851b33db9c5beb24ef785228..36557895aeb987424be3a74578cdbc1f28d712e6 100644 (file)
@@ -1271,7 +1271,11 @@ void run_one_test(void)
     /* GC_allocate_ml and GC_need_to_lock are no longer exported, and   */
     /* AO_fetch_and_add1() may be unavailable to update a counter.      */
     (void)GC_call_with_alloc_lock(inc_int_counter, &n_tests);
-#   if defined(THREADS) && defined(HANDLE_FORK)
+#   if defined(THREADS) && defined(HANDLE_FORK) \
+       && (!defined(DARWIN) || !defined(MPROTECT_VDB) \
+           || defined(NO_INCREMENTAL) || defined(MAKE_BACK_GRAPH))
+           /* FIXME: fork() is not tested on Darwin if incremental mode */
+           /* is on for now (till it would be handled properly).        */
       if (fork() == 0) {
         GC_gcollect();
         tiny_reverse_test(0);