Skip to content

Commit f358421

Browse files
committed
Protect calls to fork with a gc_lock on MacOS
On MacOS running under Rosetta there is a hang if you are calling fork from one thread and thread_suspend from another. (I believe the suspend call is attempting to suspend the forking thread) We call thread_suspend on all managed threads when doing a GC. We can avoid the collision of calls if we use mono_gc_invoke_with_gc_lock to protect the fork call. I do not believe this is needed on other platforms or chips. I suspect this is a Rosetta problem that we need to work around.
1 parent 76c3749 commit f358421

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

mono/metadata/w32process-unix.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,15 @@ close_my_fds (void)
14881488
}
14891489
#endif
14901490

1491+
#if defined (HAVE_FORK)
1492+
static void* fork_helper(void* data)
1493+
{
1494+
pid_t* pid = (pid_t*)data;
1495+
*pid = fork();
1496+
return NULL;
1497+
}
1498+
#endif
1499+
14911500
static gboolean
14921501
process_create (const gunichar2 *appname, const gunichar2 *cmdline,
14931502
const gunichar2 *cwd, StartupHandles *startup_handles, MonoW32ProcessInfo *process_info)
@@ -1849,7 +1858,12 @@ process_create (const gunichar2 *appname, const gunichar2 *cmdline,
18491858
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
18501859
}
18511860

1852-
switch (pid = fork ()) {
1861+
#if defined(HOST_DARWIN) && defined(TARGET_AMD64)
1862+
mono_gc_invoke_with_gc_lock(fork_helper, &pid);
1863+
#else
1864+
pid = fork();
1865+
#endif
1866+
switch (pid) {
18531867
case -1: /* Error */ {
18541868
mono_w32error_set_last (ERROR_OUTOFMEMORY);
18551869
ret = FALSE;

0 commit comments

Comments
 (0)