]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/mach/hurd/fork.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / mach / hurd / fork.c
CommitLineData
b168057a 1/* Copyright (C) 1994-2015 Free Software Foundation, Inc.
478b92f0 2 This file is part of the GNU C Library.
28f540f4 3
478b92f0 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
478b92f0
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
28f540f4
RM
17
18#include <errno.h>
19#include <unistd.h>
20#include <hurd.h>
21#include <hurd/signal.h>
22#include <setjmp.h>
8f480b4b 23#include <thread_state.h>
28f540f4
RM
24#include <sysdep.h> /* For stack growth direction. */
25#include "set-hooks.h"
26#include <assert.h>
27#include "hurdmalloc.h" /* XXX */
3ba7b383 28#include <tls.h>
28f540f4 29
6b87a564
UD
30#undef __fork
31
28f540f4
RM
32
33/* Things that want to be locked while forking. */
3fe9de0d 34symbol_set_declare (_hurd_fork_locks)
28f540f4
RM
35
36
7b7bab13
ST
37/* Application callbacks registered through pthread_atfork. */
38DEFINE_HOOK (_hurd_atfork_prepare_hook, (void));
39DEFINE_HOOK (_hurd_atfork_child_hook, (void));
40DEFINE_HOOK (_hurd_atfork_parent_hook, (void));
41
28f540f4
RM
42/* Things that want to be called before we fork, to prepare the parent for
43 task_create, when the new child task will inherit our address space. */
44DEFINE_HOOK (_hurd_fork_prepare_hook, (void));
45
46/* Things that want to be called when we are forking, with the above all
47 locked. They are passed the task port of the child. The child process
48 is all set up except for doing proc_child, and has no threads yet. */
49DEFINE_HOOK (_hurd_fork_setup_hook, (void));
50
51/* Things to be run in the child fork. */
52DEFINE_HOOK (_hurd_fork_child_hook, (void));
53
54/* Things to be run in the parent fork. */
55DEFINE_HOOK (_hurd_fork_parent_hook, (void));
56
57
58/* Clone the calling process, creating an exact copy.
59 Return -1 for errors, 0 to the new process,
60 and the process ID of the new process to the old process. */
61pid_t
62__fork (void)
63{
64 jmp_buf env;
65 pid_t pid;
66 size_t i;
67 error_t err;
28f540f4 68 struct hurd_sigstate *volatile ss;
28f540f4 69
7b7bab13
ST
70 RUN_HOOK (_hurd_atfork_prepare_hook, ());
71
28f540f4 72 ss = _hurd_self_sigstate ();
8f0c527e 73 __spin_lock (&ss->critical_section_lock);
11872325
RM
74
75#undef LOSE
221dc560 76#define LOSE do { assert_perror (err); goto lose; } while (0) /* XXX */
28f540f4
RM
77
78 if (! setjmp (env))
79 {
80 process_t newproc;
81 task_t newtask;
82 thread_t thread, sigthread;
83 mach_port_urefs_t thread_refs, sigthread_refs;
84 struct machine_thread_state state;
85 mach_msg_type_number_t statecount;
86 mach_port_t *portnames = NULL;
87 mach_msg_type_number_t nportnames = 0;
88 mach_port_type_t *porttypes = NULL;
89 mach_msg_type_number_t nporttypes = 0;
90 thread_t *threads = NULL;
91 mach_msg_type_number_t nthreads = 0;
3fe9de0d
RM
92 int ports_locked = 0, stopped = 0;
93
94 void resume_threads (void)
95 {
96 if (! stopped)
97 return;
98
99 assert (threads);
100
101 for (i = 0; i < nthreads; ++i)
102 if (threads[i] != ss->thread)
103 __thread_resume (threads[i]);
104 stopped = 0;
105 }
28f540f4
RM
106
107 /* Run things that prepare for forking before we create the task. */
108 RUN_HOOK (_hurd_fork_prepare_hook, ());
109
110 /* Lock things that want to be locked before we fork. */
3fe9de0d
RM
111 {
112 void *const *p;
113 for (p = symbol_set_first_element (_hurd_fork_locks);
114 ! symbol_set_end_p (_hurd_fork_locks, p);
115 ++p)
116 __mutex_lock (*p);
117 }
11872325 118 __mutex_lock (&_hurd_siglock);
e3fa2641 119
28f540f4
RM
120 newtask = MACH_PORT_NULL;
121 thread = sigthread = MACH_PORT_NULL;
122 newproc = MACH_PORT_NULL;
123
124 /* Lock all the port cells for the standard ports while we copy the
125 address space. We want to insert all the send rights into the
126 child with the same names. */
127 for (i = 0; i < _hurd_nports; ++i)
128 __spin_lock (&_hurd_ports[i].lock);
129 ports_locked = 1;
130
e3fa2641 131
17a62de1
ST
132 /* Keep our SS locked while stopping other threads, so they don't get a
133 chance to have it locked in the copied space. */
134 __spin_lock (&ss->lock);
3fe9de0d
RM
135 /* Stop all other threads while copying the address space,
136 so nothing changes. */
137 err = __proc_dostop (_hurd_ports[INIT_PORT_PROC].port, ss->thread);
17a62de1 138 __spin_unlock (&ss->lock);
3fe9de0d 139 if (!err)
478b92f0
UD
140 {
141 stopped = 1;
3fe9de0d 142
6df1b247
RM
143#define XXX_KERNEL_PAGE_FAULT_BUG /* XXX work around page fault bug in mk */
144
145#ifdef XXX_KERNEL_PAGE_FAULT_BUG
146 /* Gag me with a pitchfork.
147 The bug scenario is this:
148
149 - The page containing __mach_task_self_ is paged out.
150 - The signal thread was faulting on that page when we
151 suspended it via proc_dostop. It holds some lock, or set
152 some busy bit, or somesuch.
153 - Now this thread faults on that same page.
154 - GRATUIOUS DEADLOCK
155
156 We can break the deadlock by aborting the thread that faulted
157 first, which if the bug happened was the signal thread because
158 it is the only other thread and we just suspended it.
159 */
160 __thread_abort (_hurd_msgport_thread);
161#endif
3fe9de0d 162 /* Create the child task. It will inherit a copy of our memory. */
7595ddb8
RM
163 err = __task_create (__mach_task_self (),
164#ifdef KERN_INVALID_LEDGER
165 NULL, 0, /* OSF Mach */
166#endif
167 1, &newtask);
478b92f0 168 }
11872325
RM
169
170 /* Unlock the global signal state lock, so we do not
171 block the signal thread any longer than necessary. */
172 __mutex_unlock (&_hurd_siglock);
173
174 if (err)
175 LOSE;
28f540f4
RM
176
177 /* Fetch the names of all ports used in this task. */
178 if (err = __mach_port_names (__mach_task_self (),
179 &portnames, &nportnames,
180 &porttypes, &nporttypes))
11872325 181 LOSE;
28f540f4
RM
182 if (nportnames != nporttypes)
183 {
184 err = EGRATUITOUS;
11872325 185 LOSE;
28f540f4
RM
186 }
187
188 /* Get send rights for all the threads in this task.
189 We want to avoid giving these rights to the child. */
190 if (err = __task_threads (__mach_task_self (), &threads, &nthreads))
11872325 191 LOSE;
28f540f4
RM
192
193 /* Get the child process's proc server port. We will insert it into
194 the child with the same name as we use for our own proc server
195 port; and we will need it to set the child's message port. */
196 if (err = __proc_task2proc (_hurd_ports[INIT_PORT_PROC].port,
197 newtask, &newproc))
11872325 198 LOSE;
28f540f4
RM
199
200 /* Insert all our port rights into the child task. */
201 thread_refs = sigthread_refs = 0;
202 for (i = 0; i < nportnames; ++i)
203 {
204 if (porttypes[i] & MACH_PORT_TYPE_RECEIVE)
205 {
206 /* This is a receive right. We want to give the child task
207 its own new receive right under the same name. */
208 err = __mach_port_allocate_name (newtask,
209 MACH_PORT_RIGHT_RECEIVE,
210 portnames[i]);
211 if (err == KERN_NAME_EXISTS)
212 {
213 /* It already has a right under this name (?!). Well,
214 there is this bizarre old Mach IPC feature (in #ifdef
215 MACH_IPC_COMPAT in the ukernel) which results in new
216 tasks getting a new receive right for task special
217 port number 2. What else might be going on I'm not
218 sure. So let's check. */
219#if !MACH_IPC_COMPAT
220#define TASK_NOTIFY_PORT 2
221#endif
222 assert (({ mach_port_t thisport, notify_port;
223 mach_msg_type_name_t poly;
224 (__task_get_special_port (newtask,
225 TASK_NOTIFY_PORT,
226 &notify_port) == 0 &&
e3fa2641 227 __mach_port_extract_right
28f540f4
RM
228 (newtask,
229 portnames[i],
230 MACH_MSG_TYPE_MAKE_SEND,
231 &thisport, &poly) == 0 &&
232 (thisport == notify_port) &&
233 __mach_port_deallocate (__mach_task_self (),
234 thisport) == 0 &&
235 __mach_port_deallocate (__mach_task_self (),
236 notify_port) == 0);
237 }));
238 }
239 else if (err)
11872325 240 LOSE;
28f540f4
RM
241 if (porttypes[i] & MACH_PORT_TYPE_SEND)
242 {
243 /* Give the child as many send rights for its receive
244 right as we have for ours. */
245 mach_port_urefs_t refs;
246 mach_port_t port;
247 mach_msg_type_name_t poly;
248 if (err = __mach_port_get_refs (__mach_task_self (),
249 portnames[i],
250 MACH_PORT_RIGHT_SEND,
251 &refs))
11872325 252 LOSE;
28f540f4
RM
253 if (err = __mach_port_extract_right (newtask,
254 portnames[i],
255 MACH_MSG_TYPE_MAKE_SEND,
256 &port, &poly))
11872325 257 LOSE;
28f540f4
RM
258 if (portnames[i] == _hurd_msgport)
259 {
260 /* We just created a receive right for the child's
261 message port and are about to insert send rights
262 for it. Now, while we happen to have a send right
263 for it, give it to the proc server. */
264 mach_port_t old;
265 if (err = __proc_setmsgport (newproc, port, &old))
11872325 266 LOSE;
28f540f4
RM
267 if (old != MACH_PORT_NULL)
268 /* XXX what to do here? */
269 __mach_port_deallocate (__mach_task_self (), old);
4ca84cff
RM
270 /* The new task will receive its own exceptions
271 on its message port. */
7595ddb8
RM
272 if (err =
273#ifdef TASK_EXCEPTION_PORT
274 __task_set_special_port (newtask,
275 TASK_EXCEPTION_PORT,
276 port)
277#elif defined (EXC_MASK_ALL)
278 __task_set_exception_ports
279 (newtask, EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
280 | EXC_MASK_MACH_SYSCALL
281 | EXC_MASK_RPC_ALERT),
282 port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)
283#else
284# error task_set_exception_port?
285#endif
286 )
4ca84cff 287 LOSE;
28f540f4
RM
288 }
289 if (err = __mach_port_insert_right (newtask,
290 portnames[i],
291 port,
292 MACH_MSG_TYPE_MOVE_SEND))
11872325 293 LOSE;
28f540f4
RM
294 if (refs > 1 &&
295 (err = __mach_port_mod_refs (newtask,
296 portnames[i],
297 MACH_PORT_RIGHT_SEND,
298 refs - 1)))
11872325 299 LOSE;
28f540f4
RM
300 }
301 if (porttypes[i] & MACH_PORT_TYPE_SEND_ONCE)
302 {
303 /* Give the child a send-once right for its receive right,
304 since we have one for ours. */
305 mach_port_t port;
306 mach_msg_type_name_t poly;
307 if (err = __mach_port_extract_right
308 (newtask,
309 portnames[i],
310 MACH_MSG_TYPE_MAKE_SEND_ONCE,
311 &port, &poly))
11872325 312 LOSE;
28f540f4
RM
313 if (err = __mach_port_insert_right
314 (newtask,
315 portnames[i], port,
316 MACH_MSG_TYPE_MOVE_SEND_ONCE))
11872325 317 LOSE;
28f540f4
RM
318 }
319 }
11872325
RM
320 else if (porttypes[i] &
321 (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_DEAD_NAME))
28f540f4
RM
322 {
323 /* This is a send right or a dead name.
324 Give the child as many references for it as we have. */
7f513ec8 325 mach_port_urefs_t refs = 0, *record_refs = NULL;
28f540f4 326 mach_port_t insert;
3125073e 327 mach_msg_type_name_t insert_type = MACH_MSG_TYPE_COPY_SEND;
7119ea6d
RM
328 if (portnames[i] == newtask || portnames[i] == newproc)
329 /* Skip the name we use for the child's task or proc ports. */
28f540f4
RM
330 continue;
331 if (portnames[i] == __mach_task_self ())
332 /* For the name we use for our own task port,
333 insert the child's task port instead. */
334 insert = newtask;
335 else if (portnames[i] == _hurd_ports[INIT_PORT_PROC].port)
336 {
7119ea6d
RM
337 /* Use the proc server port for the new task. */
338 insert = newproc;
339 insert_type = MACH_MSG_TYPE_COPY_SEND;
28f540f4 340 }
3fe9de0d 341 else if (portnames[i] == ss->thread)
28f540f4
RM
342 {
343 /* For the name we use for our own thread port, we will
344 insert the thread port for the child main user thread
345 after we create it. */
346 insert = MACH_PORT_NULL;
347 record_refs = &thread_refs;
348 /* Allocate a dead name right for this name as a
478b92f0
UD
349 placeholder, so the kernel will not chose this name
350 for any other new port (it might use it for one of the
351 rights created when a thread is created). */
28f540f4
RM
352 if (err = __mach_port_allocate_name
353 (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i]))
11872325 354 LOSE;
28f540f4
RM
355 }
356 else if (portnames[i] == _hurd_msgport_thread)
357 /* For the name we use for our signal thread's thread port,
358 we will insert the thread port for the child's signal
359 thread after we create it. */
360 {
361 insert = MACH_PORT_NULL;
362 record_refs = &sigthread_refs;
363 /* Allocate a dead name right as a placeholder. */
364 if (err = __mach_port_allocate_name
365 (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i]))
11872325 366 LOSE;
28f540f4
RM
367 }
368 else
369 {
370 /* Skip the name we use for any of our own thread ports. */
371 mach_msg_type_number_t j;
372 for (j = 0; j < nthreads; ++j)
373 if (portnames[i] == threads[j])
374 break;
375 if (j < nthreads)
376 continue;
377
3125073e 378 /* Copy our own send right. */
28f540f4
RM
379 insert = portnames[i];
380 }
381 /* Find out how many user references we have for
382 the send right with this name. */
383 if (err = __mach_port_get_refs (__mach_task_self (),
384 portnames[i],
385 MACH_PORT_RIGHT_SEND,
386 record_refs ?: &refs))
11872325 387 LOSE;
28f540f4
RM
388 if (insert == MACH_PORT_NULL)
389 continue;
11872325
RM
390 if (insert == portnames[i] &&
391 (porttypes[i] & MACH_PORT_TYPE_DEAD_NAME))
392 /* This is a dead name; allocate another dead name
393 with the same name in the child. */
394 allocate_dead_name:
395 err = __mach_port_allocate_name (newtask,
396 MACH_PORT_RIGHT_DEAD_NAME,
397 portnames[i]);
398 else
399 /* Insert the chosen send right into the child. */
400 err = __mach_port_insert_right (newtask,
401 portnames[i],
a1c93156 402 insert, insert_type);
11872325 403 switch (err)
28f540f4 404 {
11872325
RM
405 case KERN_NAME_EXISTS:
406 {
407 /* It already has a send right under this name (?!).
408 Well, it starts out with a send right for its task
409 port, and inherits the bootstrap and exception ports
410 from us. */
411 mach_port_t childport;
412 mach_msg_type_name_t poly;
413 assert (__mach_port_extract_right (newtask, portnames[i],
414 MACH_MSG_TYPE_COPY_SEND,
415 &childport,
416 &poly) == 0 &&
417 childport == insert &&
418 __mach_port_deallocate (__mach_task_self (),
419 childport) == 0);
420 break;
421 }
422
423 case KERN_INVALID_CAPABILITY:
424 /* The port just died. It was a send right,
425 and now it's a dead name. */
426 goto allocate_dead_name;
427
428 default:
429 LOSE;
430 break;
431
432 case KERN_SUCCESS:
433 /* Give the child as many user references as we have. */
434 if (refs > 1 &&
435 (err = __mach_port_mod_refs (newtask,
436 portnames[i],
437 MACH_PORT_RIGHT_SEND,
438 refs - 1)))
439 LOSE;
28f540f4 440 }
28f540f4
RM
441 }
442 }
443
444 /* Unlock the standard port cells. The child must unlock its own
445 copies too. */
446 for (i = 0; i < _hurd_nports; ++i)
447 __spin_unlock (&_hurd_ports[i].lock);
448 ports_locked = 0;
449
3fe9de0d 450 /* All state has now been copied from the parent. It is safe to
478b92f0 451 resume other parent threads. */
3fe9de0d
RM
452 resume_threads ();
453
28f540f4
RM
454 /* Create the child main user thread and signal thread. */
455 if ((err = __thread_create (newtask, &thread)) ||
456 (err = __thread_create (newtask, &sigthread)))
11872325 457 LOSE;
28f540f4
RM
458
459 /* Insert send rights for those threads. We previously allocated
478b92f0
UD
460 dead name rights with the names we want to give the thread ports
461 in the child as placeholders. Now deallocate them so we can use
462 the names. */
3fe9de0d
RM
463 if ((err = __mach_port_deallocate (newtask, ss->thread)) ||
464 (err = __mach_port_insert_right (newtask, ss->thread,
28f540f4 465 thread, MACH_MSG_TYPE_COPY_SEND)))
11872325 466 LOSE;
28f540f4
RM
467 /* We have one extra user reference created at the beginning of this
468 function, accounted for by mach_port_names (and which will thus be
469 accounted for in the child below). This extra right gets consumed
470 in the child by the store into _hurd_sigthread in the child fork. */
471 if (thread_refs > 1 &&
3fe9de0d 472 (err = __mach_port_mod_refs (newtask, ss->thread,
28f540f4 473 MACH_PORT_RIGHT_SEND,
3fe9de0d 474 thread_refs)))
11872325 475 LOSE;
28f540f4
RM
476 if ((_hurd_msgport_thread != MACH_PORT_NULL) /* Let user have none. */
477 && ((err = __mach_port_deallocate (newtask, _hurd_msgport_thread)) ||
478 (err = __mach_port_insert_right (newtask, _hurd_msgport_thread,
479 sigthread,
480 MACH_MSG_TYPE_COPY_SEND))))
11872325 481 LOSE;
28f540f4
RM
482 if (sigthread_refs > 1 &&
483 (err = __mach_port_mod_refs (newtask, _hurd_msgport_thread,
484 MACH_PORT_RIGHT_SEND,
485 sigthread_refs - 1)))
11872325 486 LOSE;
28f540f4
RM
487
488 /* This seems like a convenient juncture to copy the proc server's
489 idea of what addresses our argv and envp are found at from the
490 parent into the child. Since we happen to know that the child
491 shares our memory image, it is we who should do this copying. */
492 {
493 vm_address_t argv, envp;
494 err = (__USEPORT (PROC, __proc_get_arg_locations (port, &argv, &envp))
495 ?: __proc_set_arg_locations (newproc, argv, envp));
496 if (err)
11872325 497 LOSE;
28f540f4 498 }
e3fa2641 499
28f540f4
RM
500 /* Set the child signal thread up to run the msgport server function
501 using the same signal thread stack copied from our address space.
502 We fetch the state before longjmp'ing it so that miscellaneous
503 registers not affected by longjmp (such as i386 segment registers)
504 are in their normal default state. */
505 statecount = MACHINE_THREAD_STATE_COUNT;
506 if (err = __thread_get_state (_hurd_msgport_thread,
507 MACHINE_THREAD_STATE_FLAVOR,
508 (natural_t *) &state, &statecount))
11872325 509 LOSE;
28f540f4 510#if STACK_GROWTH_UP
72e1a750
RM
511#define THREADVAR_SPACE (__hurd_threadvar_max \
512 * sizeof *__hurd_sightread_variables)
513 if (__hurd_sigthread_stack_base == 0)
514 {
515 state.SP &= __hurd_threadvar_stack_mask;
516 state.SP += __hurd_threadvar_stack_offset + THREADVAR_SPACE;
517 }
518 else
519 state.SP = __hurd_sigthread_stack_base;
28f540f4 520#else
72e1a750
RM
521 if (__hurd_sigthread_stack_end == 0)
522 {
523 /* The signal thread has a normal stack assigned by cthreads.
524 The threadvar_stack variables conveniently tell us how
525 to get to the highest address in the stack, just below
526 the per-thread variables. */
527 state.SP &= __hurd_threadvar_stack_mask;
528 state.SP += __hurd_threadvar_stack_offset;
529 }
530 else
531 state.SP = __hurd_sigthread_stack_end;
e3fa2641 532#endif
28f540f4
RM
533 MACHINE_THREAD_STATE_SET_PC (&state,
534 (unsigned long int) _hurd_msgport_receive);
535 if (err = __thread_set_state (sigthread, MACHINE_THREAD_STATE_FLAVOR,
536 (natural_t *) &state, statecount))
11872325 537 LOSE;
28f540f4
RM
538 /* We do not thread_resume SIGTHREAD here because the child
539 fork needs to do more setup before it can take signals. */
540
541 /* Set the child user thread up to return 1 from the setjmp above. */
542 _hurd_longjmp_thread_state (&state, env, 1);
3ba7b383 543
3ba7b383
RM
544 /* Do special thread setup for TLS if needed. */
545 if (err = _hurd_tls_fork (thread, &state))
546 LOSE;
3ba7b383 547
28f540f4
RM
548 if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
549 (natural_t *) &state, statecount))
11872325 550 LOSE;
28f540f4
RM
551
552 /* Get the PID of the child from the proc server. We must do this
553 before calling proc_child below, because at that point any
554 authorized POSIX.1 process may kill the child task with SIGKILL. */
555 if (err = __USEPORT (PROC, __proc_task2pid (port, newtask, &pid)))
11872325 556 LOSE;
28f540f4
RM
557
558 /* Register the child with the proc server. It is important that
559 this be that last thing we do before starting the child thread
560 running. Once proc_child has been done for the task, it appears
561 as a POSIX.1 process. Any errors we get must be detected before
562 this point, and the child must have a message port so it responds
563 to POSIX.1 signals. */
564 if (err = __USEPORT (PROC, __proc_child (port, newtask)))
11872325 565 LOSE;
28f540f4
RM
566
567 /* This must be the absolutely last thing we do; we can't assume that
568 the child will remain alive for even a moment once we do this. We
569 ignore errors because we have committed to the fork and are not
570 allowed to return them after the process becomes visible to
571 POSIX.1 (which happened right above when we called proc_child). */
572 (void) __thread_resume (thread);
573
574 lose:
575 if (ports_locked)
576 for (i = 0; i < _hurd_nports; ++i)
577 __spin_unlock (&_hurd_ports[i].lock);
578
3fe9de0d
RM
579 resume_threads ();
580
28f540f4
RM
581 if (newtask != MACH_PORT_NULL)
582 {
583 if (err)
584 __task_terminate (newtask);
585 __mach_port_deallocate (__mach_task_self (), newtask);
586 }
587 if (thread != MACH_PORT_NULL)
588 __mach_port_deallocate (__mach_task_self (), thread);
589 if (sigthread != MACH_PORT_NULL)
590 __mach_port_deallocate (__mach_task_self (), sigthread);
591 if (newproc != MACH_PORT_NULL)
592 __mach_port_deallocate (__mach_task_self (), newproc);
28f540f4
RM
593
594 if (portnames)
595 __vm_deallocate (__mach_task_self (),
596 (vm_address_t) portnames,
597 nportnames * sizeof (*portnames));
598 if (porttypes)
599 __vm_deallocate (__mach_task_self (),
600 (vm_address_t) porttypes,
601 nporttypes * sizeof (*porttypes));
602 if (threads)
603 {
604 for (i = 0; i < nthreads; ++i)
605 __mach_port_deallocate (__mach_task_self (), threads[i]);
606 __vm_deallocate (__mach_task_self (),
607 (vm_address_t) threads,
608 nthreads * sizeof (*threads));
609 }
610
611 /* Run things that want to run in the parent to restore it to
612 normality. Usually prepare hooks and parent hooks are
613 symmetrical: the prepare hook arrests state in some way for the
614 fork, and the parent hook restores the state for the parent to
615 continue executing normally. */
616 RUN_HOOK (_hurd_fork_parent_hook, ());
617 }
618 else
619 {
620 struct hurd_sigstate *oldstates;
621
622 /* We are the child task. Unlock the standard port cells, which were
478b92f0
UD
623 locked in the parent when we copied its memory. The parent has
624 inserted send rights with the names that were in the cells then. */
28f540f4
RM
625 for (i = 0; i < _hurd_nports; ++i)
626 __spin_unlock (&_hurd_ports[i].lock);
627
4ac9bb2e
RM
628 /* We are one of the (exactly) two threads in this new task, we
629 will take the task-global signals. */
3fe9de0d 630 _hurd_sigthread = ss->thread;
28f540f4 631
4ac9bb2e
RM
632 /* Claim our sigstate structure and unchain the rest: the
633 threads existed in the parent task but don't exist in this
634 task (the child process). Delay freeing them until later
635 because some of the further setup and unlocking might be
636 required for free to work. Before we finish cleaning up,
637 we will reclaim the signal thread's sigstate structure (if
638 it had one). */
28f540f4
RM
639 oldstates = _hurd_sigstates;
640 if (oldstates == ss)
641 oldstates = ss->next;
642 else
643 {
644 while (_hurd_sigstates->next != ss)
645 _hurd_sigstates = _hurd_sigstates->next;
646 _hurd_sigstates->next = ss->next;
647 }
648 ss->next = NULL;
649 _hurd_sigstates = ss;
11872325 650 __mutex_unlock (&_hurd_siglock);
28f540f4
RM
651
652 /* Fetch our new process IDs from the proc server. No need to
653 refetch our pgrp; it is always inherited from the parent (so
654 _hurd_pgrp is already correct), and the proc server will send us a
655 proc_newids notification when it changes. */
656 err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid,
657 &_hurd_orphaned));
658
b07c5668 659 /* Forking clears the trace flag. */
8f0c527e 660 __sigemptyset (&_hurdsig_traced);
b07c5668 661
28f540f4
RM
662 /* Run things that want to run in the child task to set up. */
663 RUN_HOOK (_hurd_fork_child_hook, ());
664
665 /* Set up proc server-assisted fault recovery for the signal thread. */
666 _hurdsig_fault_init ();
667
668 /* Start the signal thread listening on the message port. */
669 if (!err)
670 err = __thread_resume (_hurd_msgport_thread);
671
4ac9bb2e
RM
672 /* Reclaim the signal thread's sigstate structure and free the
673 other old sigstate structures. */
28f540f4
RM
674 while (oldstates != NULL)
675 {
676 struct hurd_sigstate *next = oldstates->next;
4ac9bb2e
RM
677
678 if (oldstates->thread == _hurd_msgport_thread)
679 {
680 /* If we have a second signal state structure then we
681 must have been through here before--not good. */
682 assert (_hurd_sigstates->next == 0);
683 _hurd_sigstates->next = oldstates;
684 oldstates->next = 0;
685 }
686 else
687 free (oldstates);
688
28f540f4
RM
689 oldstates = next;
690 }
4ac9bb2e 691
28f540f4
RM
692 /* XXX what to do if we have any errors here? */
693
694 pid = 0;
695 }
696
697 /* Unlock things we locked before creating the child task.
698 They are locked in both the parent and child tasks. */
3fe9de0d
RM
699 {
700 void *const *p;
701 for (p = symbol_set_first_element (_hurd_fork_locks);
702 ! symbol_set_end_p (_hurd_fork_locks, p);
703 ++p)
704 __mutex_unlock (*p);
705 }
28f540f4 706
11872325 707 _hurd_critical_section_unlock (ss);
28f540f4 708
7b7bab13
ST
709 if (!err)
710 {
711 if (pid != 0)
712 RUN_HOOK (_hurd_atfork_parent_hook, ());
713 else
714 RUN_HOOK (_hurd_atfork_child_hook, ());
715 }
716
28f540f4
RM
717 return err ? __hurd_fail (err) : pid;
718}
d1436edc 719libc_hidden_def (__fork)
28f540f4
RM
720
721weak_alias (__fork, fork)