summaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/fork.c')
-rw-r--r--sysdeps/mach/hurd/fork.c55
1 files changed, 21 insertions, 34 deletions
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 3e7501f9a1..2d1e64c8d1 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,6 +27,7 @@
#include <assert.h>
#include "hurdmalloc.h" /* XXX */
#include <tls.h>
+#include <malloc/malloc-internal.h>
#undef __fork
@@ -118,6 +119,13 @@ __fork (void)
}
__mutex_lock (&_hurd_siglock);
+ /* Acquire malloc locks. This needs to come last because fork
+ handlers may use malloc, and the libio list lock has an
+ indirect malloc dependency as well (via the getdelim
+ function). */
+ call_function_static_weak (__malloc_fork_lock_parent);
+ _hurd_malloc_fork_prepare ();
+
newtask = MACH_PORT_NULL;
thread = sigthread = MACH_PORT_NULL;
newproc = MACH_PORT_NULL;
@@ -206,38 +214,9 @@ __fork (void)
{
/* This is a receive right. We want to give the child task
its own new receive right under the same name. */
- err = __mach_port_allocate_name (newtask,
- MACH_PORT_RIGHT_RECEIVE,
- portnames[i]);
- if (err == KERN_NAME_EXISTS)
- {
- /* It already has a right under this name (?!). Well,
- there is this bizarre old Mach IPC feature (in #ifdef
- MACH_IPC_COMPAT in the ukernel) which results in new
- tasks getting a new receive right for task special
- port number 2. What else might be going on I'm not
- sure. So let's check. */
-#if !MACH_IPC_COMPAT
-#define TASK_NOTIFY_PORT 2
-#endif
- assert (({ mach_port_t thisport, notify_port;
- mach_msg_type_name_t poly;
- (__task_get_special_port (newtask,
- TASK_NOTIFY_PORT,
- &notify_port) == 0 &&
- __mach_port_extract_right
- (newtask,
- portnames[i],
- MACH_MSG_TYPE_MAKE_SEND,
- &thisport, &poly) == 0 &&
- (thisport == notify_port) &&
- __mach_port_deallocate (__mach_task_self (),
- thisport) == 0 &&
- __mach_port_deallocate (__mach_task_self (),
- notify_port) == 0);
- }));
- }
- else if (err)
+ if (err = __mach_port_allocate_name (newtask,
+ MACH_PORT_RIGHT_RECEIVE,
+ portnames[i]))
LOSE;
if (porttypes[i] & MACH_PORT_TYPE_SEND)
{
@@ -528,7 +507,7 @@ __fork (void)
MACHINE_THREAD_STATE_SET_PC (&state,
(unsigned long int) _hurd_msgport_receive);
- /* Do special thread setup for TLS if needed. */
+ /* Do special signal thread setup for TLS if needed. */
if (err = _hurd_tls_fork (sigthread, _hurd_msgport_thread, &state))
LOSE;
@@ -608,6 +587,10 @@ __fork (void)
nthreads * sizeof (*threads));
}
+ /* Release malloc locks. */
+ _hurd_malloc_fork_parent ();
+ call_function_static_weak (__malloc_fork_unlock_parent);
+
/* Run things that want to run in the parent to restore it to
normality. Usually prepare hooks and parent hooks are
symmetrical: the prepare hook arrests state in some way for the
@@ -659,6 +642,10 @@ __fork (void)
/* Forking clears the trace flag. */
__sigemptyset (&_hurdsig_traced);
+ /* Release malloc locks. */
+ _hurd_malloc_fork_child ();
+ call_function_static_weak (__malloc_fork_unlock_child);
+
/* Run things that want to run in the child task to set up. */
RUN_HOOK (_hurd_fork_child_hook, ());