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