summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2012-04-02 20:31:22 +0200
committerIvan Maidanski <ivmai@mail.ru>2012-04-03 06:15:54 +0200
commitcad34343056a5f9b4598b5ddc36ed8ce0e264399 (patch)
treeb0e0408635970f85a7584372ad6557449c1122f4
parent1555aa8dd31db657c0ad5eed618757157783c2e5 (diff)
FIX: Disable incremental mode on Darwin if fork handling requested
* doc/README.macros (NO_HANDLE_FORK): Replace back with HANDLE_FORK and update. * include/private/gcconfig.h (CAN_HANDLE_FORK): Define also for Darwin in case of MPROTECT_VDB. * misc.c (GC_set_handle_fork): Handle Darwin properly; add comment. * os_dep.c (GC_dirty_init): Do not turn on GC_dirty_maintained for Darwin if GC_handle_fork is on; add comment; remove FIXME. * pthread_support.c (GC_fork_prepare_proc): Remove WARN for Darwin (since GC_dirty_maintained is off in that case). * pthread_support.c (GC_fork_child_proc): Remove comment (for Darwin).
-rw-r--r--doc/README.macros6
-rw-r--r--include/private/gcconfig.h2
-rw-r--r--misc.c5
-rw-r--r--os_dep.c19
-rw-r--r--pthread_support.c13
5 files changed, 22 insertions, 23 deletions
diff --git a/doc/README.macros b/doc/README.macros
index c745eb3..cf6a14d 100644
--- a/doc/README.macros
+++ b/doc/README.macros
@@ -433,9 +433,9 @@ STUBBORN_ALLOC Allows allocation of "hard to change" objects, and thus
makes incremental collection easier. Was enabled by default until 6.0.
Rarely used, to my knowledge.
-NO_HANDLE_FORK (Unix only) Do not attempt to make GC_malloc() work in
- a child process fork()'ed from a multi-threaded parent. (Might be required
- if pthread_atfork is missing.)
+HANDLE_FORK (Unix and Cygwin only) Attempt by default to make GC_malloc()
+ work in a child process fork()'ed from a multi-threaded parent. Not fully
+ POSIX-compliant and could be disabled at runtime (before GC_INIT).
TEST_WITH_SYSTEM_MALLOC Causes gctest to allocate (and leak) large
chunks of memory with the standard system malloc. This will cause the root
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 7ecc80f..4d27bde 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -2594,7 +2594,7 @@
#if !defined(CAN_HANDLE_FORK) && !defined(NO_HANDLE_FORK) \
&& ((defined(GC_PTHREADS) && !defined(HURD) && !defined(NACL) \
&& !defined(PLATFORM_ANDROID) && !defined(GC_WIN32_PTHREADS)) \
- || defined(HANDLE_FORK))
+ || (defined(DARWIN) && defined(MPROTECT_VDB)) || defined(HANDLE_FORK))
/* Attempts (where supported and requested) to make GC_malloc work in */
/* a child process fork'ed from a multi-threaded parent. */
# define CAN_HANDLE_FORK
diff --git a/misc.c b/misc.c
index fac069a..5267998 100644
--- a/misc.c
+++ b/misc.c
@@ -169,10 +169,11 @@ GC_API void GC_CALL GC_set_handle_fork(int value)
# ifdef CAN_HANDLE_FORK
if (!GC_is_initialized)
GC_handle_fork = (GC_bool)value;
-# elif defined(THREADS)
- /* FIXME: Handle Darwin case. */
+# elif defined(THREADS) || (defined(DARWIN) && defined(MPROTECT_VDB))
if (!GC_is_initialized && value)
ABORT("fork() handling disabled");
+# else
+ /* No at-fork handler is needed in the single-threaded mode. */
# endif
}
diff --git a/os_dep.c b/os_dep.c
index 070756a..17dabcd 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -4094,6 +4094,21 @@ GC_INNER void GC_dirty_init(void)
pthread_attr_t attr;
exception_mask_t mask;
+# ifdef CAN_HANDLE_FORK
+ if (GC_handle_fork) {
+ /* To both support GC incremental mode and GC functions usage in */
+ /* the forked child, pthread_atfork should be used to install */
+ /* handlers that switch off GC_dirty_maintained in the child */
+ /* gracefully (unprotecting all pages and clearing */
+ /* GC_mach_handler_thread). For now, we just disable incremental */
+ /* mode if fork() handling is requested by the client. */
+ if (GC_print_stats)
+ GC_log_printf(
+ "GC incremental mode disabled since fork() handling requested\n");
+ return;
+ }
+# endif
+
if (GC_print_stats == VERBOSE)
GC_log_printf(
"Initializing mach/darwin mprotect virtual dirty bit implementation\n");
@@ -4142,10 +4157,6 @@ 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 41234ab..652e4a7 100644
--- a/pthread_support.c
+++ b/pthread_support.c
@@ -846,14 +846,6 @@ 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)
@@ -886,11 +878,6 @@ STATIC void GC_fork_child_proc(void)
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
/* Turn off parallel marking in the child, since we are probably */