From: Ivan Maidanski Date: Fri, 24 Feb 2012 07:29:48 +0000 (+0400) Subject: Fix fork() handling for Darwin partially X-Git-Tag: gc7_3alpha2~97 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee0301906ae01bdd6d3a0fb4105c8a45d6bfae82;p=gc Fix fork() handling for Darwin partially (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. --- diff --git a/os_dep.c b/os_dep.c index 00467675..6a15816f 100644 --- 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) diff --git a/pthread_support.c b/pthread_support.c index 9a9c9d34..e43f20a0 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -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 diff --git a/tests/test.c b/tests/test.c index e2134526..36557895 100644 --- a/tests/test.c +++ b/tests/test.c @@ -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);