Back to index

glibc  2.9
fork.c
Go to the documentation of this file.
00001 /* Copyright (C) 1994,1995,1996,1997,1999,2001,2002,2004,2005,2006
00002        Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <unistd.h>
00022 #include <hurd.h>
00023 #include <hurd/signal.h>
00024 #include <setjmp.h>
00025 #include <thread_state.h>
00026 #include <sysdep.h>         /* For stack growth direction.  */
00027 #include "set-hooks.h"
00028 #include <assert.h>
00029 #include "hurdmalloc.h"            /* XXX */
00030 #include <tls.h>
00031 
00032 #undef __fork
00033 
00034 
00035 /* Things that want to be locked while forking.  */
00036 symbol_set_declare (_hurd_fork_locks)
00037 
00038 
00039 /* Things that want to be called before we fork, to prepare the parent for
00040    task_create, when the new child task will inherit our address space.  */
00041 DEFINE_HOOK (_hurd_fork_prepare_hook, (void));
00042 
00043 /* Things that want to be called when we are forking, with the above all
00044    locked.  They are passed the task port of the child.  The child process
00045    is all set up except for doing proc_child, and has no threads yet.  */
00046 DEFINE_HOOK (_hurd_fork_setup_hook, (void));
00047 
00048 /* Things to be run in the child fork.  */
00049 DEFINE_HOOK (_hurd_fork_child_hook, (void));
00050 
00051 /* Things to be run in the parent fork.  */
00052 DEFINE_HOOK (_hurd_fork_parent_hook, (void));
00053 
00054 
00055 /* Clone the calling process, creating an exact copy.
00056    Return -1 for errors, 0 to the new process,
00057    and the process ID of the new process to the old process.  */
00058 pid_t
00059 __fork (void)
00060 {
00061   jmp_buf env;
00062   pid_t pid;
00063   size_t i;
00064   error_t err;
00065   struct hurd_sigstate *volatile ss;
00066 
00067   ss = _hurd_self_sigstate ();
00068   __spin_lock (&ss->critical_section_lock);
00069 
00070 #undef LOSE
00071 #define LOSE do { assert_perror (err); goto lose; } while (0) /* XXX */
00072 
00073   if (! setjmp (env))
00074     {
00075       process_t newproc;
00076       task_t newtask;
00077       thread_t thread, sigthread;
00078       mach_port_urefs_t thread_refs, sigthread_refs;
00079       struct machine_thread_state state;
00080       mach_msg_type_number_t statecount;
00081       mach_port_t *portnames = NULL;
00082       mach_msg_type_number_t nportnames = 0;
00083       mach_port_type_t *porttypes = NULL;
00084       mach_msg_type_number_t nporttypes = 0;
00085       thread_t *threads = NULL;
00086       mach_msg_type_number_t nthreads = 0;
00087       int ports_locked = 0, stopped = 0;
00088 
00089       void resume_threads (void)
00090        {
00091          if (! stopped)
00092            return;
00093 
00094          assert (threads);
00095 
00096          for (i = 0; i < nthreads; ++i)
00097            if (threads[i] != ss->thread)
00098              __thread_resume (threads[i]);
00099          stopped = 0;
00100        }
00101 
00102       /* Run things that prepare for forking before we create the task.  */
00103       RUN_HOOK (_hurd_fork_prepare_hook, ());
00104 
00105       /* Lock things that want to be locked before we fork.  */
00106       {
00107        void *const *p;
00108        for (p = symbol_set_first_element (_hurd_fork_locks);
00109             ! symbol_set_end_p (_hurd_fork_locks, p);
00110             ++p)
00111          __mutex_lock (*p);
00112       }
00113       __mutex_lock (&_hurd_siglock);
00114 
00115       newtask = MACH_PORT_NULL;
00116       thread = sigthread = MACH_PORT_NULL;
00117       newproc = MACH_PORT_NULL;
00118 
00119       /* Lock all the port cells for the standard ports while we copy the
00120         address space.  We want to insert all the send rights into the
00121         child with the same names.  */
00122       for (i = 0; i < _hurd_nports; ++i)
00123        __spin_lock (&_hurd_ports[i].lock);
00124       ports_locked = 1;
00125 
00126 
00127       /* Stop all other threads while copying the address space,
00128         so nothing changes.  */
00129       err = __proc_dostop (_hurd_ports[INIT_PORT_PROC].port, ss->thread);
00130       if (!err)
00131        {
00132          stopped = 1;
00133 
00134 #define XXX_KERNEL_PAGE_FAULT_BUG /* XXX work around page fault bug in mk */
00135 
00136 #ifdef XXX_KERNEL_PAGE_FAULT_BUG
00137          /* Gag me with a pitchfork.
00138             The bug scenario is this:
00139 
00140             - The page containing __mach_task_self_ is paged out.
00141             - The signal thread was faulting on that page when we
00142               suspended it via proc_dostop.  It holds some lock, or set
00143               some busy bit, or somesuch.
00144             - Now this thread faults on that same page.
00145             - GRATUIOUS DEADLOCK
00146 
00147             We can break the deadlock by aborting the thread that faulted
00148             first, which if the bug happened was the signal thread because
00149             it is the only other thread and we just suspended it.
00150             */
00151          __thread_abort (_hurd_msgport_thread);
00152 #endif
00153          /* Create the child task.  It will inherit a copy of our memory.  */
00154          err = __task_create (__mach_task_self (),
00155 #ifdef KERN_INVALID_LEDGER
00156                             NULL, 0,      /* OSF Mach */
00157 #endif
00158                             1, &newtask);
00159        }
00160 
00161       /* Unlock the global signal state lock, so we do not
00162         block the signal thread any longer than necessary.  */
00163       __mutex_unlock (&_hurd_siglock);
00164 
00165       if (err)
00166        LOSE;
00167 
00168       /* Fetch the names of all ports used in this task.  */
00169       if (err = __mach_port_names (__mach_task_self (),
00170                                &portnames, &nportnames,
00171                                &porttypes, &nporttypes))
00172        LOSE;
00173       if (nportnames != nporttypes)
00174        {
00175          err = EGRATUITOUS;
00176          LOSE;
00177        }
00178 
00179       /* Get send rights for all the threads in this task.
00180         We want to avoid giving these rights to the child.  */
00181       if (err = __task_threads (__mach_task_self (), &threads, &nthreads))
00182        LOSE;
00183 
00184       /* Get the child process's proc server port.  We will insert it into
00185         the child with the same name as we use for our own proc server
00186         port; and we will need it to set the child's message port.  */
00187       if (err = __proc_task2proc (_hurd_ports[INIT_PORT_PROC].port,
00188                               newtask, &newproc))
00189        LOSE;
00190 
00191       /* Insert all our port rights into the child task.  */
00192       thread_refs = sigthread_refs = 0;
00193       for (i = 0; i < nportnames; ++i)
00194        {
00195          if (porttypes[i] & MACH_PORT_TYPE_RECEIVE)
00196            {
00197              /* This is a receive right.  We want to give the child task
00198                its own new receive right under the same name.  */
00199              err = __mach_port_allocate_name (newtask,
00200                                           MACH_PORT_RIGHT_RECEIVE,
00201                                           portnames[i]);
00202              if (err == KERN_NAME_EXISTS)
00203               {
00204                 /* It already has a right under this name (?!).  Well,
00205                    there is this bizarre old Mach IPC feature (in #ifdef
00206                    MACH_IPC_COMPAT in the ukernel) which results in new
00207                    tasks getting a new receive right for task special
00208                    port number 2.  What else might be going on I'm not
00209                    sure.  So let's check.  */
00210 #if !MACH_IPC_COMPAT
00211 #define TASK_NOTIFY_PORT 2
00212 #endif
00213                 assert (({ mach_port_t thisport, notify_port;
00214                           mach_msg_type_name_t poly;
00215                           (__task_get_special_port (newtask,
00216                                                  TASK_NOTIFY_PORT,
00217                                                  &notify_port) == 0 &&
00218                            __mach_port_extract_right
00219                            (newtask,
00220                             portnames[i],
00221                             MACH_MSG_TYPE_MAKE_SEND,
00222                             &thisport, &poly) == 0 &&
00223                            (thisport == notify_port) &&
00224                            __mach_port_deallocate (__mach_task_self (),
00225                                                 thisport) == 0 &&
00226                            __mach_port_deallocate (__mach_task_self (),
00227                                                 notify_port) == 0);
00228                         }));
00229               }
00230              else if (err)
00231               LOSE;
00232              if (porttypes[i] & MACH_PORT_TYPE_SEND)
00233               {
00234                 /* Give the child as many send rights for its receive
00235                    right as we have for ours.  */
00236                 mach_port_urefs_t refs;
00237                 mach_port_t port;
00238                 mach_msg_type_name_t poly;
00239                 if (err = __mach_port_get_refs (__mach_task_self (),
00240                                             portnames[i],
00241                                             MACH_PORT_RIGHT_SEND,
00242                                             &refs))
00243                   LOSE;
00244                 if (err = __mach_port_extract_right (newtask,
00245                                                  portnames[i],
00246                                                  MACH_MSG_TYPE_MAKE_SEND,
00247                                                  &port, &poly))
00248                   LOSE;
00249                 if (portnames[i] == _hurd_msgport)
00250                   {
00251                     /* We just created a receive right for the child's
00252                       message port and are about to insert send rights
00253                       for it.  Now, while we happen to have a send right
00254                       for it, give it to the proc server.  */
00255                     mach_port_t old;
00256                     if (err = __proc_setmsgport (newproc, port, &old))
00257                      LOSE;
00258                     if (old != MACH_PORT_NULL)
00259                      /* XXX what to do here? */
00260                      __mach_port_deallocate (__mach_task_self (), old);
00261                     /* The new task will receive its own exceptions
00262                       on its message port.  */
00263                     if (err =
00264 #ifdef TASK_EXCEPTION_PORT
00265                        __task_set_special_port (newtask,
00266                                              TASK_EXCEPTION_PORT,
00267                                              port)
00268 #elif defined (EXC_MASK_ALL)
00269                        __task_set_exception_ports
00270                        (newtask, EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
00271                                                | EXC_MASK_MACH_SYSCALL
00272                                                | EXC_MASK_RPC_ALERT),
00273                         port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)
00274 #else
00275 # error task_set_exception_port?
00276 #endif
00277                        )
00278                      LOSE;
00279                   }
00280                 if (err = __mach_port_insert_right (newtask,
00281                                                 portnames[i],
00282                                                 port,
00283                                                 MACH_MSG_TYPE_MOVE_SEND))
00284                   LOSE;
00285                 if (refs > 1 &&
00286                     (err = __mach_port_mod_refs (newtask,
00287                                              portnames[i],
00288                                              MACH_PORT_RIGHT_SEND,
00289                                              refs - 1)))
00290                   LOSE;
00291               }
00292              if (porttypes[i] & MACH_PORT_TYPE_SEND_ONCE)
00293               {
00294                 /* Give the child a send-once right for its receive right,
00295                    since we have one for ours.  */
00296                 mach_port_t port;
00297                 mach_msg_type_name_t poly;
00298                 if (err = __mach_port_extract_right
00299                     (newtask,
00300                      portnames[i],
00301                      MACH_MSG_TYPE_MAKE_SEND_ONCE,
00302                      &port, &poly))
00303                   LOSE;
00304                 if (err = __mach_port_insert_right
00305                     (newtask,
00306                      portnames[i], port,
00307                      MACH_MSG_TYPE_MOVE_SEND_ONCE))
00308                   LOSE;
00309               }
00310            }
00311          else if (porttypes[i] &
00312                  (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_DEAD_NAME))
00313            {
00314              /* This is a send right or a dead name.
00315                Give the child as many references for it as we have.  */
00316              mach_port_urefs_t refs, *record_refs = NULL;
00317              mach_port_t insert;
00318              mach_msg_type_name_t insert_type = MACH_MSG_TYPE_COPY_SEND;
00319              if (portnames[i] == newtask || portnames[i] == newproc)
00320               /* Skip the name we use for the child's task or proc ports.  */
00321               continue;
00322              if (portnames[i] == __mach_task_self ())
00323               /* For the name we use for our own task port,
00324                  insert the child's task port instead.  */
00325               insert = newtask;
00326              else if (portnames[i] == _hurd_ports[INIT_PORT_PROC].port)
00327               {
00328                 /* Use the proc server port for the new task.  */
00329                 insert = newproc;
00330                 insert_type = MACH_MSG_TYPE_COPY_SEND;
00331               }
00332              else if (portnames[i] == ss->thread)
00333               {
00334                 /* For the name we use for our own thread port, we will
00335                    insert the thread port for the child main user thread
00336                    after we create it.  */
00337                 insert = MACH_PORT_NULL;
00338                 record_refs = &thread_refs;
00339                 /* Allocate a dead name right for this name as a
00340                    placeholder, so the kernel will not chose this name
00341                    for any other new port (it might use it for one of the
00342                    rights created when a thread is created).  */
00343                 if (err = __mach_port_allocate_name
00344                     (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i]))
00345                   LOSE;
00346               }
00347              else if (portnames[i] == _hurd_msgport_thread)
00348               /* For the name we use for our signal thread's thread port,
00349                  we will insert the thread port for the child's signal
00350                  thread after we create it.  */
00351               {
00352                 insert = MACH_PORT_NULL;
00353                 record_refs = &sigthread_refs;
00354                 /* Allocate a dead name right as a placeholder.  */
00355                 if (err = __mach_port_allocate_name
00356                     (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i]))
00357                   LOSE;
00358               }
00359              else
00360               {
00361                 /* Skip the name we use for any of our own thread ports.  */
00362                 mach_msg_type_number_t j;
00363                 for (j = 0; j < nthreads; ++j)
00364                   if (portnames[i] == threads[j])
00365                     break;
00366                 if (j < nthreads)
00367                   continue;
00368 
00369                 /* Copy our own send right.  */
00370                 insert = portnames[i];
00371               }
00372              /* Find out how many user references we have for
00373                the send right with this name.  */
00374              if (err = __mach_port_get_refs (__mach_task_self (),
00375                                          portnames[i],
00376                                          MACH_PORT_RIGHT_SEND,
00377                                          record_refs ?: &refs))
00378               LOSE;
00379              if (insert == MACH_PORT_NULL)
00380               continue;
00381              if (insert == portnames[i] &&
00382                 (porttypes[i] & MACH_PORT_TYPE_DEAD_NAME))
00383               /* This is a dead name; allocate another dead name
00384                  with the same name in the child.  */
00385              allocate_dead_name:
00386               err = __mach_port_allocate_name (newtask,
00387                                            MACH_PORT_RIGHT_DEAD_NAME,
00388                                            portnames[i]);
00389              else
00390               /* Insert the chosen send right into the child.  */
00391               err = __mach_port_insert_right (newtask,
00392                                           portnames[i],
00393                                           insert, insert_type);
00394              switch (err)
00395               {
00396               case KERN_NAME_EXISTS:
00397                 {
00398                   /* It already has a send right under this name (?!).
00399                      Well, it starts out with a send right for its task
00400                      port, and inherits the bootstrap and exception ports
00401                      from us.  */
00402                   mach_port_t childport;
00403                   mach_msg_type_name_t poly;
00404                   assert (__mach_port_extract_right (newtask, portnames[i],
00405                                                  MACH_MSG_TYPE_COPY_SEND,
00406                                                  &childport,
00407                                                  &poly) == 0 &&
00408                          childport == insert &&
00409                          __mach_port_deallocate (__mach_task_self (),
00410                                               childport) == 0);
00411                   break;
00412                 }
00413 
00414               case KERN_INVALID_CAPABILITY:
00415                 /* The port just died.  It was a send right,
00416                    and now it's a dead name.  */
00417                 goto allocate_dead_name;
00418 
00419               default:
00420                 LOSE;
00421                 break;
00422 
00423               case KERN_SUCCESS:
00424                 /* Give the child as many user references as we have.  */
00425                 if (refs > 1 &&
00426                     (err = __mach_port_mod_refs (newtask,
00427                                              portnames[i],
00428                                              MACH_PORT_RIGHT_SEND,
00429                                              refs - 1)))
00430                   LOSE;
00431               }
00432            }
00433        }
00434 
00435       /* Unlock the standard port cells.  The child must unlock its own
00436         copies too.  */
00437       for (i = 0; i < _hurd_nports; ++i)
00438        __spin_unlock (&_hurd_ports[i].lock);
00439       ports_locked = 0;
00440 
00441       /* All state has now been copied from the parent.  It is safe to
00442         resume other parent threads.  */
00443       resume_threads ();
00444 
00445       /* Create the child main user thread and signal thread.  */
00446       if ((err = __thread_create (newtask, &thread)) ||
00447          (err = __thread_create (newtask, &sigthread)))
00448        LOSE;
00449 
00450       /* Insert send rights for those threads.  We previously allocated
00451         dead name rights with the names we want to give the thread ports
00452         in the child as placeholders.  Now deallocate them so we can use
00453         the names.  */
00454       if ((err = __mach_port_deallocate (newtask, ss->thread)) ||
00455          (err = __mach_port_insert_right (newtask, ss->thread,
00456                                       thread, MACH_MSG_TYPE_COPY_SEND)))
00457        LOSE;
00458       /* We have one extra user reference created at the beginning of this
00459         function, accounted for by mach_port_names (and which will thus be
00460         accounted for in the child below).  This extra right gets consumed
00461         in the child by the store into _hurd_sigthread in the child fork.  */
00462       if (thread_refs > 1 &&
00463          (err = __mach_port_mod_refs (newtask, ss->thread,
00464                                    MACH_PORT_RIGHT_SEND,
00465                                    thread_refs)))
00466        LOSE;
00467       if ((_hurd_msgport_thread != MACH_PORT_NULL) /* Let user have none.  */
00468          && ((err = __mach_port_deallocate (newtask, _hurd_msgport_thread)) ||
00469              (err = __mach_port_insert_right (newtask, _hurd_msgport_thread,
00470                                           sigthread,
00471                                           MACH_MSG_TYPE_COPY_SEND))))
00472        LOSE;
00473       if (sigthread_refs > 1 &&
00474          (err = __mach_port_mod_refs (newtask, _hurd_msgport_thread,
00475                                    MACH_PORT_RIGHT_SEND,
00476                                    sigthread_refs - 1)))
00477        LOSE;
00478 
00479       /* This seems like a convenient juncture to copy the proc server's
00480         idea of what addresses our argv and envp are found at from the
00481         parent into the child.  Since we happen to know that the child
00482         shares our memory image, it is we who should do this copying.  */
00483       {
00484        vm_address_t argv, envp;
00485        err = (__USEPORT (PROC, __proc_get_arg_locations (port, &argv, &envp))
00486               ?: __proc_set_arg_locations (newproc, argv, envp));
00487        if (err)
00488          LOSE;
00489       }
00490 
00491       /* Set the child signal thread up to run the msgport server function
00492         using the same signal thread stack copied from our address space.
00493         We fetch the state before longjmp'ing it so that miscellaneous
00494         registers not affected by longjmp (such as i386 segment registers)
00495         are in their normal default state.  */
00496       statecount = MACHINE_THREAD_STATE_COUNT;
00497       if (err = __thread_get_state (_hurd_msgport_thread,
00498                                 MACHINE_THREAD_STATE_FLAVOR,
00499                                 (natural_t *) &state, &statecount))
00500        LOSE;
00501 #if STACK_GROWTH_UP
00502 #define THREADVAR_SPACE (__hurd_threadvar_max \
00503                       * sizeof *__hurd_sightread_variables)
00504       if (__hurd_sigthread_stack_base == 0)
00505        {
00506          state.SP &= __hurd_threadvar_stack_mask;
00507          state.SP += __hurd_threadvar_stack_offset + THREADVAR_SPACE;
00508        }
00509       else
00510        state.SP = __hurd_sigthread_stack_base;
00511 #else
00512       if (__hurd_sigthread_stack_end == 0)
00513        {
00514          /* The signal thread has a normal stack assigned by cthreads.
00515             The threadvar_stack variables conveniently tell us how
00516             to get to the highest address in the stack, just below
00517             the per-thread variables.  */
00518          state.SP &= __hurd_threadvar_stack_mask;
00519          state.SP += __hurd_threadvar_stack_offset;
00520        }
00521       else
00522        state.SP = __hurd_sigthread_stack_end;
00523 #endif
00524       MACHINE_THREAD_STATE_SET_PC (&state,
00525                                (unsigned long int) _hurd_msgport_receive);
00526       if (err = __thread_set_state (sigthread, MACHINE_THREAD_STATE_FLAVOR,
00527                                 (natural_t *) &state, statecount))
00528        LOSE;
00529       /* We do not thread_resume SIGTHREAD here because the child
00530         fork needs to do more setup before it can take signals.  */
00531 
00532       /* Set the child user thread up to return 1 from the setjmp above.  */
00533       _hurd_longjmp_thread_state (&state, env, 1);
00534 
00535       /* Do special thread setup for TLS if needed.  */
00536       if (err = _hurd_tls_fork (thread, &state))
00537        LOSE;
00538 
00539       if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
00540                                 (natural_t *) &state, statecount))
00541        LOSE;
00542 
00543       /* Get the PID of the child from the proc server.  We must do this
00544         before calling proc_child below, because at that point any
00545         authorized POSIX.1 process may kill the child task with SIGKILL.  */
00546       if (err = __USEPORT (PROC, __proc_task2pid (port, newtask, &pid)))
00547        LOSE;
00548 
00549       /* Register the child with the proc server.  It is important that
00550         this be that last thing we do before starting the child thread
00551         running.  Once proc_child has been done for the task, it appears
00552         as a POSIX.1 process.  Any errors we get must be detected before
00553         this point, and the child must have a message port so it responds
00554         to POSIX.1 signals.  */
00555       if (err = __USEPORT (PROC, __proc_child (port, newtask)))
00556        LOSE;
00557 
00558       /* This must be the absolutely last thing we do; we can't assume that
00559         the child will remain alive for even a moment once we do this.  We
00560         ignore errors because we have committed to the fork and are not
00561         allowed to return them after the process becomes visible to
00562         POSIX.1 (which happened right above when we called proc_child).  */
00563       (void) __thread_resume (thread);
00564 
00565     lose:
00566       if (ports_locked)
00567        for (i = 0; i < _hurd_nports; ++i)
00568          __spin_unlock (&_hurd_ports[i].lock);
00569 
00570       resume_threads ();
00571 
00572       if (newtask != MACH_PORT_NULL)
00573        {
00574          if (err)
00575            __task_terminate (newtask);
00576          __mach_port_deallocate (__mach_task_self (), newtask);
00577        }
00578       if (thread != MACH_PORT_NULL)
00579        __mach_port_deallocate (__mach_task_self (), thread);
00580       if (sigthread != MACH_PORT_NULL)
00581        __mach_port_deallocate (__mach_task_self (), sigthread);
00582       if (newproc != MACH_PORT_NULL)
00583        __mach_port_deallocate (__mach_task_self (), newproc);
00584 
00585       if (portnames)
00586        __vm_deallocate (__mach_task_self (),
00587                       (vm_address_t) portnames,
00588                       nportnames * sizeof (*portnames));
00589       if (porttypes)
00590        __vm_deallocate (__mach_task_self (),
00591                       (vm_address_t) porttypes,
00592                       nporttypes * sizeof (*porttypes));
00593       if (threads)
00594        {
00595          for (i = 0; i < nthreads; ++i)
00596            __mach_port_deallocate (__mach_task_self (), threads[i]);
00597          __vm_deallocate (__mach_task_self (),
00598                         (vm_address_t) threads,
00599                         nthreads * sizeof (*threads));
00600        }
00601 
00602       /* Run things that want to run in the parent to restore it to
00603         normality.  Usually prepare hooks and parent hooks are
00604         symmetrical: the prepare hook arrests state in some way for the
00605         fork, and the parent hook restores the state for the parent to
00606         continue executing normally.  */
00607       RUN_HOOK (_hurd_fork_parent_hook, ());
00608     }
00609   else
00610     {
00611       struct hurd_sigstate *oldstates;
00612 
00613       /* We are the child task.  Unlock the standard port cells, which were
00614         locked in the parent when we copied its memory.  The parent has
00615         inserted send rights with the names that were in the cells then.  */
00616       for (i = 0; i < _hurd_nports; ++i)
00617        __spin_unlock (&_hurd_ports[i].lock);
00618 
00619       /* We are one of the (exactly) two threads in this new task, we
00620         will take the task-global signals.  */
00621       _hurd_sigthread = ss->thread;
00622 
00623       /* Claim our sigstate structure and unchain the rest: the
00624         threads existed in the parent task but don't exist in this
00625         task (the child process).  Delay freeing them until later
00626         because some of the further setup and unlocking might be
00627         required for free to work.  Before we finish cleaning up,
00628         we will reclaim the signal thread's sigstate structure (if
00629         it had one).  */
00630       oldstates = _hurd_sigstates;
00631       if (oldstates == ss)
00632        oldstates = ss->next;
00633       else
00634        {
00635          while (_hurd_sigstates->next != ss)
00636            _hurd_sigstates = _hurd_sigstates->next;
00637          _hurd_sigstates->next = ss->next;
00638        }
00639       ss->next = NULL;
00640       _hurd_sigstates = ss;
00641       __mutex_unlock (&_hurd_siglock);
00642 
00643       /* Fetch our new process IDs from the proc server.  No need to
00644         refetch our pgrp; it is always inherited from the parent (so
00645         _hurd_pgrp is already correct), and the proc server will send us a
00646         proc_newids notification when it changes.  */
00647       err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid,
00648                                         &_hurd_orphaned));
00649 
00650       /* Forking clears the trace flag.  */
00651       __sigemptyset (&_hurdsig_traced);
00652 
00653       /* Run things that want to run in the child task to set up.  */
00654       RUN_HOOK (_hurd_fork_child_hook, ());
00655 
00656       /* Set up proc server-assisted fault recovery for the signal thread.  */
00657       _hurdsig_fault_init ();
00658 
00659       /* Start the signal thread listening on the message port.  */
00660       if (!err)
00661        err = __thread_resume (_hurd_msgport_thread);
00662 
00663       /* Reclaim the signal thread's sigstate structure and free the
00664         other old sigstate structures.  */
00665       while (oldstates != NULL)
00666        {
00667          struct hurd_sigstate *next = oldstates->next;
00668 
00669          if (oldstates->thread == _hurd_msgport_thread)
00670            {
00671              /* If we have a second signal state structure then we
00672                must have been through here before--not good.  */
00673              assert (_hurd_sigstates->next == 0);
00674              _hurd_sigstates->next = oldstates;
00675              oldstates->next = 0;
00676            }
00677          else
00678            free (oldstates);
00679 
00680          oldstates = next;
00681        }
00682 
00683       /* XXX what to do if we have any errors here? */
00684 
00685       pid = 0;
00686     }
00687 
00688   /* Unlock things we locked before creating the child task.
00689      They are locked in both the parent and child tasks.  */
00690   {
00691     void *const *p;
00692     for (p = symbol_set_first_element (_hurd_fork_locks);
00693         ! symbol_set_end_p (_hurd_fork_locks, p);
00694         ++p)
00695       __mutex_unlock (*p);
00696   }
00697 
00698   _hurd_critical_section_unlock (ss);
00699 
00700   return err ? __hurd_fail (err) : pid;
00701 }
00702 libc_hidden_def (__fork)
00703 
00704 weak_alias (__fork, fork)