OSDN Git Service

* sigproc.cc (mychild): Reimplement as list scan.
authorcgf <cgf>
Sun, 5 Dec 2004 19:41:23 +0000 (19:41 +0000)
committercgf <cgf>
Sun, 5 Dec 2004 19:41:23 +0000 (19:41 +0000)
(proc_subproc): Don't mess with pinfo if it's myself.
* child_info.h (child_info_types): Label enum for _PROC constants.
(child_info::child_info): New constructor.
(child_info::~child_info): New destructor.
(child_info::sync): Declare new function.
(child_info_fork::child_info_fork): New constructor.
(child_info_spawn::child_info_spawn): Remove old constructor.
(child_info_spawn::child_info_spawn): New constructor.
* dcrt0.cc (dll_crt0_0): Use correct sizeof when doing sanity check on passed
in child_info.  Signal readiness to parent when not forking (and not spawning).
* fork.cc (sync_with_child): Delete.
(resume_child): Remove extra argument.
(sync_with_parent): Use child_info method to sync with parent.
(fork_child): Don't close fork_info->subproc_ready since that is now handled by
the destructor.
(fork_parent): Remove subproc_ready stuff.  Use child_info sync method for
waiting..  Set start time here for child.  Rename "forked" to "child".
(fork): Check ch.subproc_ready for validity here.
* pinfo.h (_pinfo::exec_sendsig): Temp storage for exec stub which may be
staying around to handle non-cygwin captive process.
(_pinfo::exec_dwProcessId): Ditto.
(_pinfo::_lock): Renamed from lock.
(_pinfo::lock): New method.
(_pinfo::unlock): Ditto.
(_pinfo::initialize_lock): Ditto.
* pinfo.cc (set_myself): Use initialize_lock method to initialize myself lock.
Set "exec" fields in _pinfo to zero to indicate that we've started
successfully.  Set start time here when appropriate.
(_pinfo::commune_send): Use pinfo lock/unlock methods.
(proc_waiter): Remove special case for non-cywin processes.  Reinstitute
handling for PID_NOCLDSTOP.
* sigproc.cc (proc_subproc): Set proper EAGAIN errno when process table is
filled.
(sig_send): Use exec_* fields from _pinfo for sending signals if the the _pinfo
sendsig never materializes.
(child_info::child_info): New constructor, renamed from init_child_info.
Zeroes child_info structure and sets appropriate fields in structure based on
chtype.
(child_info::~child_info): New destructor.  Closes subproc_ready if it exists.
(child_info_fork::child_info_fork): New constructor.
(child_info_spawn::child_info_spawn): New constructor.
(child_info::ready): New function.  Signals parent when child is ready.
(child_info::sync): New function.  Wait for child to signal us or process to
die.
(remove_proc): Remove closing of hProcess since this should now be handled
shortly after process creation.
* spawn.cc (spawn_guts): Use child_info_spawn constructor rather than
init_child_info.  Save exec_sendsig and exec_dwProcessId in execing _pinfo.
Rely on child_info constructor to properly set parent_wr_proc_pipe in ciresrv.
Revert to previous determination on whether to start a process in suspended
mode.  Remove reparenting stuff.  Just keep a stub around if starting a
non-cygwin process.

winsup/cygwin/ChangeLog
winsup/cygwin/child_info.h
winsup/cygwin/dcrt0.cc
winsup/cygwin/fork.cc
winsup/cygwin/include/sys/cygwin.h
winsup/cygwin/pinfo.cc
winsup/cygwin/pinfo.h
winsup/cygwin/sigproc.cc
winsup/cygwin/spawn.cc

index dc15981..74423f2 100644 (file)
@@ -1,3 +1,65 @@
+2004-12-05  Christopher Faylor  <cgf@timesys.com>
+
+       * sigproc.cc (mychild): Reimplement as list scan.
+       (proc_subproc): Don't mess with pinfo if it's myself.
+
+2004-12-05  Christopher Faylor  <cgf@timesys.com>
+
+       * child_info.h (child_info_types): Label enum for _PROC constants.
+       (child_info::child_info): New constructor.
+       (child_info::~child_info): New destructor.
+       (child_info::sync): Declare new function.
+       (child_info_fork::child_info_fork): New constructor.
+       (child_info_spawn::child_info_spawn): Remove old constructor.
+       (child_info_spawn::child_info_spawn): New constructor.
+       * dcrt0.cc (dll_crt0_0): Use correct sizeof when doing sanity check on
+       passed in child_info.  Signal readiness to parent when not forking (and
+       not spawning).
+       * fork.cc (sync_with_child): Delete.
+       (resume_child): Remove extra argument.
+       (sync_with_parent): Use child_info method to sync with parent.
+       (fork_child): Don't close fork_info->subproc_ready since that is now
+       handled by the destructor.
+       (fork_parent): Remove subproc_ready stuff.  Use child_info sync method
+       for waiting..  Set start time here for child.  Rename "forked" to
+       "child".
+       (fork): Check ch.subproc_ready for validity here.
+       * pinfo.h (_pinfo::exec_sendsig): Temp storage for exec stub which may
+       be staying around to handle non-cygwin captive process.
+       (_pinfo::exec_dwProcessId): Ditto.
+       (_pinfo::_lock): Renamed from lock.
+       (_pinfo::lock): New method.
+       (_pinfo::unlock): Ditto.
+       (_pinfo::initialize_lock): Ditto.
+       * pinfo.cc (set_myself): Use initialize_lock method to initialize
+       myself lock.  Set "exec" fields in _pinfo to zero to indicate that
+       we've started successfully.  Set start time here when appropriate.
+       (_pinfo::commune_send): Use pinfo lock/unlock methods.
+       (proc_waiter): Remove special case for non-cywin processes.
+       Reinstitute handling for PID_NOCLDSTOP.
+       * sigproc.cc (proc_subproc): Set proper EAGAIN errno when process table
+       is filled.
+       (sig_send): Use exec_* fields from _pinfo for sending signals if the
+       the _pinfo sendsig never materializes.
+       (child_info::child_info): New constructor, renamed from init_child_info.
+       Zeroes child_info structure and sets appropriate fields in structure
+       based on chtype.
+       (child_info::~child_info): New destructor.  Closes subproc_ready if it
+       exists.
+       (child_info_fork::child_info_fork): New constructor.
+       (child_info_spawn::child_info_spawn): New constructor.
+       (child_info::ready): New function.  Signals parent when child is ready.
+       (child_info::sync): New function.  Wait for child to signal us or
+       process to die.
+       (remove_proc): Remove closing of hProcess since this should now be
+       handled shortly after process creation.
+       * spawn.cc (spawn_guts): Use child_info_spawn constructor rather than
+       init_child_info.  Save exec_sendsig and exec_dwProcessId in execing
+       _pinfo.  Rely on child_info constructor to properly set
+       parent_wr_proc_pipe in ciresrv.  Revert to previous determination on
+       whether to start a process in suspended mode.  Remove reparenting
+       stuff.  Just keep a stub around if starting a non-cygwin process.
+
 2004-12-05  Bas van Gompel  <cygwin-patch@bavag.tmfweb.nl>
 
        * fhandler.cc (fhandler_base::read): Remove superfluous check in
index 48186e6..601fdfd 100644 (file)
@@ -10,7 +10,7 @@ details. */
 
 #include <setjmp.h>
 
-enum
+enum child_info_types
 {
   _PROC_EXEC,
   _PROC_SPAWN,
@@ -51,6 +51,10 @@ public:
   HANDLE cygheap_h;
   HANDLE parent_wr_proc_pipe;
   unsigned fhandler_union_cb;
+  child_info (unsigned, child_info_types);
+  ~child_info ();
+  void ready (bool);
+  bool sync (pinfo&, DWORD);
 };
 
 class mount_info;
@@ -64,6 +68,7 @@ public:
   jmp_buf jmp;         // where child will jump to
   void *stacktop;      // location of top of parent stack
   void *stackbottom;   // location of bottom of parent stack
+  child_info_fork ();
 };
 
 class fhandler_base;
@@ -84,7 +89,6 @@ class child_info_spawn: public child_info
 public:
   cygheap_exec_info *moreinfo;
 
-  child_info_spawn (): moreinfo (NULL) {}
   ~child_info_spawn ()
   {
     if (moreinfo)
@@ -101,6 +105,7 @@ public:
        cfree (moreinfo);
       }
   }
+  child_info_spawn (child_info_types);
 };
 
 void __stdcall init_child_info (DWORD, child_info *, HANDLE);
index 51b197e..bd9cf1c 100644 (file)
@@ -618,13 +618,15 @@ dll_crt0_0 ()
          case _PROC_SPAWN:
          case _PROC_EXEC:
            if (!should_be_cb)
-             should_be_cb = sizeof (child_info);
+             should_be_cb = sizeof (child_info_spawn);
            if (should_be_cb != child_proc_info->cb)
              multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb);
            else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)
              multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));
            else
              {
+               if (child_proc_info->type != _PROC_FORK)
+                 child_proc_info->ready (true);
                cygwin_user_h = child_proc_info->user_h;
                break;
              }
index 4744202..422b191 100644 (file)
@@ -107,68 +107,8 @@ fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
   return 0;
 }
 
-/* Wait for child to finish what it's doing and signal us.
-   We don't want to wait forever here.If there's a problem somewhere
-   it'll hang the entire system (since all forks are mutex'd). If we
-   time out, set errno = EAGAIN and hope the app tries again.  */
 static int
-sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
-                bool hang_child, const char *s)
-{
-  /* We also add the child process handle to the wait. If the child fails
-     to initialize (eg. because of a missing dll). Then this
-     handle will become signalled. This stops a *looong* timeout wait.
-  */
-  HANDLE w4[2];
-
-  debug_printf ("waiting for child.  reason: %s, hang_child %d", s,
-               hang_child);
-  w4[1] = pi.hProcess;
-  w4[0] = subproc_ready;
-  DWORD rc = WaitForMultipleObjects (2, w4, FALSE, FORK_WAIT_TIMEOUT);
-
-  if (rc == WAIT_OBJECT_0 ||
-      WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0)
-    /* That's ok */;
-  else if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
-    {
-      if (rc != WAIT_FAILED)
-       system_printf ("WaitForMultipleObjects timed out");
-      else
-       system_printf ("WaitForMultipleObjects failed, %E");
-      set_errno (EAGAIN);
-      syscall_printf ("-1 = fork(), WaitForMultipleObjects failed");
-      TerminateProcess (pi.hProcess, 1);
-      return 0;
-    }
-  else
-    {
-      /* Child died. Clean up and exit. */
-      DWORD errcode;
-      GetExitCodeProcess (pi.hProcess, &errcode);
-      /* Fix me.  This is not enough.  The fork should not be considered
-       * to have failed if the process was essentially killed by a signal.
-       */
-      if (errcode != STATUS_CONTROL_C_EXIT)
-       {
-         system_printf ("child %u(%p) died before initialization with status code %p",
-                        cygwin_pid (pi.dwProcessId), pi.hProcess, errcode);
-         system_printf ("*** child state %s", s);
-#ifdef DEBUGGING
-         try_to_debug ();
-#endif
-       }
-      set_errno (EAGAIN);
-      syscall_printf ("Child died before subproc_ready signalled");
-      return 0;
-    }
-
-  debug_printf ("child signalled me");
-  return 1;
-}
-
-static int
-resume_child (PROCESS_INFORMATION &pi, HANDLE forker_finished)
+resume_child (HANDLE forker_finished)
 {
   SetEvent (forker_finished);
   debug_printf ("signalled child");
@@ -182,9 +122,7 @@ static void __stdcall
 sync_with_parent (const char *s, bool hang_self)
 {
   debug_printf ("signalling parent: %s", s);
-  /* Tell our parent we're waiting. */
-  if (!SetEvent (fork_info->subproc_ready))
-    api_fatal ("fork child - SetEvent for %s failed, %E", s);
+  fork_info->ready (false);
   if (hang_self)
     {
       HANDLE h = fork_info->forker_finished;
@@ -281,7 +219,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
     }
 
   ForceCloseHandle (hParent);
-  (void) ForceCloseHandle1 (fork_info->subproc_ready, subproc_ready);
   (void) ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
 
   _my_tls.fixup_after_fork ();
@@ -308,7 +245,7 @@ slow_pid_reuse (HANDLE h)
 
   if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
     nfork_procs = 0;
-  /* Keep a list of handles to forked processes sitting around to prevent
+  /* Keep a list of handles to child processes sitting around to prevent
      Windows from reusing the same pid n times in a row.  Having the same pids
      close in succesion confuses bash.  Keeping a handle open will stop
      windows from reusing the same pid.  */
@@ -330,7 +267,7 @@ static int __stdcall
 fork_parent (HANDLE& hParent, dll *&first_dll,
             bool& load_dlls, void *stack_here, child_info_fork &ch)
 {
-  HANDLE subproc_ready, forker_finished;
+  HANDLE forker_finished;
   DWORD rc;
   PROCESS_INFORMATION pi = {0, NULL, 0, 0};
 
@@ -379,35 +316,22 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
   /* This will help some of the confusion.  */
   fflush (stdout);
 
-  subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
-  if (subproc_ready == NULL)
-    {
-      CloseHandle (hParent);
-      system_printf ("unable to allocate subproc_ready event, %E");
-      return -1;
-    }
   forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
   if (forker_finished == NULL)
     {
       CloseHandle (hParent);
-      CloseHandle (subproc_ready);
       system_printf ("unable to allocate forker_finished event, %E");
       return -1;
     }
 
-  ProtectHandleINH (subproc_ready);
   ProtectHandleINH (forker_finished);
 
-  init_child_info (PROC_FORK, &ch, subproc_ready);
-
   ch.forker_finished = forker_finished;
-  ch.parent_wr_proc_pipe = myself->wr_proc_pipe == INVALID_HANDLE_VALUE
-                          ? NULL : myself->wr_proc_pipe;
 
   stack_base (ch);
 
   si.cb = sizeof (STARTUPINFO);
-  si.lpReserved2 = (LPBYTE)&ch;
+  si.lpReserved2 = (LPBYTE) &ch;
   si.cbReserved2 = sizeof (ch);
 
   /* Remove impersonation */
@@ -437,7 +361,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
     {
       __seterrno ();
       syscall_printf ("CreateProcessA failed, %E");
-      ForceCloseHandle (subproc_ready);
       ForceCloseHandle (forker_finished);
       /* Restore impersonation */
       cygheap->user.reimpersonate ();
@@ -457,10 +380,11 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
       ResumeThread (pi.hThread);
     }
 
-  int forked_pid = cygwin_pid (pi.dwProcessId);
-  pinfo forked (forked_pid, 1);
+  int child_pid = cygwin_pid (pi.dwProcessId);
+  pinfo child (child_pid, 1);
+  child->start_time = time (NULL); /* Register child's starting time. */
 
-  if (!forked)
+  if (!child)
     {
       syscall_printf ("pinfo failed");
       if (get_errno () != ENOMEM)
@@ -470,7 +394,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
 
   /* Initialize things that are done later in dll_crt0_1 that aren't done
      for the forkee.  */
-  strcpy (forked->progname, myself->progname);
+  strcpy (child->progname, myself->progname);
 
   /* Restore impersonation */
   cygheap->user.reimpersonate ();
@@ -478,18 +402,18 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
   ProtectHandle (pi.hThread);
   /* Protect the handle but name it similarly to the way it will
      be called in subproc handling. */
-  ProtectHandle1 (pi.hProcess, childhProc);
+  ProtectHandle (pi.hProcess);
 
   /* Fill in fields in the child's process table entry.  */
-  forked->dwProcessId = pi.dwProcessId;
-  forked.hProcess = pi.hProcess;
+  child->dwProcessId = pi.dwProcessId;
+  child.hProcess = pi.hProcess;
 
   /* Hopefully, this will succeed.  The alternative to doing things this
      way is to reserve space prior to calling CreateProcess and then fill
      it in afterwards.  This requires more bookkeeping than I like, though,
      so we'll just do it the easy way.  So, terminate any child process if
      we can't actually record the pid in the internal table. */
-  if (!forked.remember ())
+  if (!child.remember ())
     {
       TerminateProcess (pi.hProcess, 1);
       set_errno (EAGAIN);
@@ -501,8 +425,11 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
 #endif
 
   /* Wait for subproc to initialize itself. */
-  if (!sync_with_child (pi, subproc_ready, true, "waiting for longjmp"))
-    goto cleanup;
+  if (!ch.sync (child, FORK_WAIT_TIMEOUT))
+    {
+      system_printf ("child %d died waiting for longjmp before initialization", child_pid);
+      goto cleanup;
+    }
 
   /* CHILD IS STOPPED */
   debug_printf ("child is alive (but stopped)");
@@ -547,9 +474,13 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
     }
 
   /* Start thread, and wait for it to reload dlls.  */
-  if (!resume_child (pi, forker_finished) ||
-      !sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))
+  if (!resume_child (forker_finished))
     goto cleanup;
+  else if (!ch.sync (child, FORK_WAIT_TIMEOUT))
+    {
+      system_printf ("child %d died waiting for dll loading", child_pid);
+      goto cleanup;
+    }
 
   /* If DLLs were loaded in the parent, then the child has reloaded all
      of them and is now waiting to have all of the individual data and
@@ -567,17 +498,17 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
            goto cleanup;
        }
       /* Start the child up again. */
-      (void) resume_child (pi, forker_finished);
+      (void) resume_child (forker_finished);
     }
 
-  ForceCloseHandle (subproc_ready);
+  ForceCloseHandle (pi.hProcess);
   ForceCloseHandle (pi.hThread);
   ForceCloseHandle (forker_finished);
   forker_finished = NULL;
   pi.hThread = NULL;
   pthread::atforkparent ();
 
-  return forked_pid;
+  return child_pid;
 
 /* Common cleanup code for failure cases */
  cleanup:
@@ -589,8 +520,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
     ForceCloseHandle1 (pi.hProcess, childhProc);
   if (pi.hThread)
     ForceCloseHandle (pi.hThread);
-  if (subproc_ready)
-    ForceCloseHandle (subproc_ready);
   if (forker_finished)
     ForceCloseHandle (forker_finished);
   return -1;
@@ -618,6 +547,11 @@ fork ()
   myself->set_has_pgid_children ();
 
   child_info_fork ch;
+  if (ch.subproc_ready == NULL)
+    {
+      system_printf ("unable to allocate subproc_ready event, %E");
+      return -1;
+    }
 
   sig_send (NULL, __SIGHOLD);
   int res = setjmp (ch.jmp);
index b8c9973..172de6e 100644 (file)
@@ -87,24 +87,24 @@ unsigned long cygwin_internal (cygwin_getinfo_types, ...);
 /* Flags associated with process_state */
 enum
 {
-  PID_IN_USE          = 0x0001, /* Entry in use. */
-  PID_ZOMBIE          = 0x0002, /* Child exited: no parent wait. */
-  PID_STOPPED         = 0x0004, /* Waiting for SIGCONT. */
-  PID_TTYIN           = 0x0008, /* Waiting for terminal input. */
-  PID_TTYOU           = 0x0010, /* Waiting for terminal output. */
-  PID_ORPHANED        = 0x0020, /* Member of an orphaned process group. */
-  PID_ACTIVE          = 0x0040, /* Pid accepts signals. */
-  PID_CYGPARENT               = 0x0080, /* Set if parent was a cygwin app. */
-  PID_MAP_RW          = 0x0100, /* Flag to open map rw. */
-  PID_MYSELF          = 0x0200, /* Flag that pid is me. */
-  PID_NOCLDSTOP               = 0x0400, /* Set if no SIGCHLD signal on stop. */
-  PID_INITIALIZING     = 0x0800, /* Set until ready to receive signals. */
-  PID_USETTY          = 0x1000, /* Setting this enables or disables cygwin's */
-                                /*  tty support.  This is inherited by */
-                                /*  all execed or forked processes. */
-  PID_ALLPIDS         = 0x2000, /* child has execed */
-  PID_EXECED          = 0x4000, /* redirect to original pid info block */
-  PID_NOREDIR         = 0x8000, /* don't redirect if execed */
+  PID_IN_USE          = 0x00001, /* Entry in use. */
+  PID_ZOMBIE          = 0x00002, /* Child exited: no parent wait. */
+  PID_STOPPED         = 0x00004, /* Waiting for SIGCONT. */
+  PID_TTYIN           = 0x00008, /* Waiting for terminal input. */
+  PID_TTYOU           = 0x00010, /* Waiting for terminal output. */
+  PID_ORPHANED        = 0x00020, /* Member of an orphaned process group. */
+  PID_ACTIVE          = 0x00040, /* Pid accepts signals. */
+  PID_CYGPARENT               = 0x00080, /* Set if parent was a cygwin app. */
+  PID_MAP_RW          = 0x00100, /* Flag to open map rw. */
+  PID_MYSELF          = 0x00200, /* Flag that pid is me. */
+  PID_NOCLDSTOP               = 0x00400, /* Set if no SIGCHLD signal on stop. */
+  PID_INITIALIZING     = 0x00800, /* Set until ready to receive signals. */
+  PID_USETTY          = 0x01000, /* Setting this enables or disables cygwin's
+                                    tty support.  This is inherited by
+                                    all execed or forked processes. */
+  PID_ALLPIDS         = 0x02000, /* used by pinfo scanner */
+  PID_EXECED          = 0x04000, /* redirect to original pid info block */
+  PID_NOREDIR         = 0x08000, /* don't redirect if execed */
   PID_EXITED          = 0x80000000 /* Free entry. */
 };
 
index 62dd63d..ebc6d07 100644 (file)
@@ -50,21 +50,25 @@ set_myself (HANDLE h)
     cygheap->pid = cygwin_pid (GetCurrentProcessId ());
   myself.init (cygheap->pid, PID_IN_USE | PID_MYSELF, h);
   myself->process_state |= PID_IN_USE;
-  myself->start_time = time (NULL); /* Register our starting time. */
+  myself->dwProcessId = GetCurrentProcessId ();
 
   (void) GetModuleFileName (NULL, myself->progname, sizeof (myself->progname));
   if (!strace.active)
     strace.hello ();
   debug_printf ("myself->dwProcessId %u", myself->dwProcessId);
-  InitializeCriticalSection (&myself.lock);
-  myself->dwProcessId = GetCurrentProcessId ();
+  myself.initialize_lock ();
   if (h)
     {
       /* here if execed */
       static pinfo NO_COPY myself_identity;
       myself_identity.init (cygwin_pid (myself->dwProcessId), PID_EXECED);
+      myself->start_time = time (NULL); /* Register our starting time. */
+      myself->exec_sendsig = NULL;
+      myself->exec_dwProcessId = 0;
     }
-  else if (myself->wr_proc_pipe)
+  else if (!myself->wr_proc_pipe)
+    myself->start_time = time (NULL); /* Register our starting time. */
+  else
     {
       /* We've inherited the parent's wr_proc_pipe.  We don't need it,
         so close it. */
@@ -522,7 +526,7 @@ _pinfo::commune_send (DWORD code, ...)
       __seterrno ();
       goto err;
     }
-  EnterCriticalSection (&myself.lock);
+  myself.lock ();
   myself->tothem = tome;
   myself->fromthem = fromme;
   myself->hello_pid = pid;
@@ -626,7 +630,7 @@ err:
 
 out:
   myself->hello_pid = 0;
-  LeaveCriticalSection (&myself.lock);
+  myself.unlock ();
   return res;
 }
 
@@ -710,13 +714,6 @@ proc_waiter (void *arg)
          /* Child exited.  Do some cleanup and signal myself.  */
          CloseHandle (vchild.rd_proc_pipe);
          vchild.rd_proc_pipe = NULL;
-
-         if (vchild->process_state != PID_EXITED && vchild.hProcess)
-           {
-             DWORD exit_code;
-             if (GetExitCodeProcess (vchild.hProcess, &exit_code))
-               vchild->exitcode = (exit_code & 0xff) << 8;
-           }
          if (WIFEXITED (vchild->exitcode))
            si.si_sigval.sival_int = CLD_EXITED;
          else if (WCOREDUMP (vchild->exitcode))
@@ -730,33 +727,13 @@ proc_waiter (void *arg)
        case SIGTTOU:
        case SIGTSTP:
        case SIGSTOP:
+         if (ISSTATE (myself, PID_NOCLDSTOP))  // FIXME: No need for this flag to be in _pinfo any longer
+           continue;
          /* Child stopped.  Signal myself.  */
          si.si_sigval.sival_int = CLD_STOPPED;
          break;
        case SIGCONT:
          continue;
-       case __ALERT_REPARENT: /* sigh */
-         /* spawn_guts has signalled us that it has just started a new
-            subprocess which will take over this cygwin pid.  */
-
-         /* We need to keep a handle to the original windows process which
-            represents the cygwin process around to make sure that the
-            windows pid is not reused before we are through with it.
-            So, detect the first time that a subprocess calls exec
-            and save the current hprocess in the pid_handle field.
-            On subsequent execs just close the handle. */
-         if (!vchild.hProcess)
-           /* something went wrong.  oh well. */;
-         else if (vchild.pid_handle)
-           ForceCloseHandle1 (vchild.hProcess, childhProc);
-         else
-           vchild.pid_handle = vchild.hProcess;
-         vchild.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE,
-                                        vchild->dwProcessId);
-         vchild->cygstarted++;
-         if (vchild.hProcess)
-           ProtectHandle1 (vchild.hProcess, childhProc);
-         continue;
        default:
          system_printf ("unknown value %d on proc pipe", buf);
          continue;
@@ -790,6 +767,40 @@ proc_waiter (void *arg)
   return 0;
 }
 
+void
+proc_pipe::set (bool closeem)
+{
+  myself.lock ();
+  if (!CreatePipe (&in, &out, &sec_none_nih, 16))
+    {
+      system_printf ("couldn't create pipe, %E");
+      return;
+    }
+  /* Duplicate the write end of the pipe into the subprocess.  Make it inheritable
+     so that all of the execed children get it.  */
+  if (!DuplicateHandle (hMainProc, out, hMainProc, &out, 0, TRUE,
+                       DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
+    {
+      CloseHandle (in);
+      in = out = NULL;
+      system_printf ("couldn't make handle %p noninheritable, %E", out);
+      return;
+    }
+  _closeem = closeem;
+}
+
+proc_pipe::~proc_pipe ()
+{
+  if (_closeem)
+    {
+      if (in)
+       CloseHandle (in);
+      if (out)
+       CloseHandle (out);
+    }
+  myself.unlock ();
+}
+
 /* function to set up the process pipe and kick off proc_waiter */
 int
 pinfo::wait ()
index e1d5d35..c249fe1 100644 (file)
@@ -111,6 +111,8 @@ public:
 
   /* signals */
   HANDLE sendsig;
+  HANDLE exec_sendsig;
+  DWORD exec_dwProcessId;
 private:
   sigset_t sig_mask;
 public:
@@ -132,14 +134,14 @@ class pinfo
 public:
   HANDLE rd_proc_pipe;
   HANDLE hProcess;
-  CRITICAL_SECTION lock;
+  CRITICAL_SECTION _lock;
   /* Handle associated with initial Windows pid which started it all. */
   HANDLE pid_handle;
   void init (pid_t, DWORD, HANDLE = NULL) __attribute__ ((regparm(3)));
   pinfo () {}
   pinfo (_pinfo *x): procinfo (x), hProcess (NULL), pid_handle (NULL) {}
   pinfo (pid_t n) : rd_proc_pipe (NULL), hProcess (NULL), pid_handle (NULL) {init (n, 0);}
-  pinfo (pid_t n, DWORD flag) : rd_proc_pipe (NULL), hProcess (NULL), pid_handle (NULL)  {init (n, flag);}
+  pinfo (pid_t n, DWORD flag) : rd_proc_pipe (NULL), hProcess (NULL), pid_handle (NULL) {init (n, flag);}
   void release ();
   int wait () __attribute__ ((regparm (1)));
   ~pinfo ()
@@ -147,7 +149,9 @@ public:
     if (destroy && procinfo)
       release ();
   }
-
+  void initialize_lock () {InitializeCriticalSection (&_lock);}
+  void lock () {EnterCriticalSection (&_lock);}
+  void unlock () {LeaveCriticalSection (&_lock);}
   _pinfo *operator -> () const {return procinfo;}
   int operator == (pinfo *x) const {return x->procinfo == procinfo;}
   int operator == (pinfo &x) const {return x.procinfo == procinfo;}
@@ -175,6 +179,20 @@ public:
   void set_acl();
 };
 
+class proc_pipe
+{
+  bool _closeem;
+public:
+  HANDLE in;
+  HANDLE out;
+  void set (bool);
+  proc_pipe (bool closeem) {set (closeem);}
+  proc_pipe () : _closeem (false), in (NULL), out (NULL) {};
+  void close () {_closeem = true;}
+  ~proc_pipe ();
+  int operator == (int x) {return (int) in == x;}
+};
+
 #define ISSTATE(p, f)  (!!((p)->process_state & f))
 #define NOTSTATE(p, f) (!((p)->process_state & f))
 
index b1fea52..d7c57b1 100644 (file)
@@ -200,19 +200,18 @@ proc_exists (_pinfo *p)
   return p && !(p->process_state & (PID_EXITED | PID_ZOMBIE));
 }
 
-/* Return 1 if this is one of our children, zero otherwise.
-   FIXME: This really should be integrated with the rest of the proc_subproc
-   testing.  Scanning these lists twice is inefficient. */
-bool __stdcall
+/* Return true if this is one of our children, false otherwise.  */
+static inline bool __stdcall
 mychild (int pid)
 {
-  pinfo p (pid);
-  return p && p->ppid == myself->pid;
+  for (int i = 0; i < nprocs; i++)
+    if (procs[i]->pid == pid)
+      return true;
+  return false;
 }
 
 /* Handle all subprocess requests
  */
-#define vchild (*((pinfo *) val))
 int __stdcall
 proc_subproc (DWORD what, DWORD val)
 {
@@ -223,6 +222,7 @@ proc_subproc (DWORD what, DWORD val)
   waitq *w;
 
 #define wval    ((waitq *) val)
+#define vchild (*((pinfo *) val))
 
   sigproc_printf ("args: %x, %d", what, val);
 
@@ -244,18 +244,21 @@ proc_subproc (DWORD what, DWORD val)
          sigproc_printf ("proc table overflow: hit %d processes, pid %d\n",
                          nprocs, vchild->pid);
          rc = 0;
-         set_errno (EMFILE);   // FIXMENOW - what's the right errno?
+         set_errno (EAGAIN);
          break;
        }
 
-      vchild->ppid = myself->pid;
-      vchild->uid = myself->uid;
-      vchild->gid = myself->gid;
-      vchild->pgid = myself->pgid;
-      vchild->sid = myself->sid;
-      vchild->ctty = myself->ctty;
-      vchild->cygstarted = true;
-      vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY);
+      if (vchild != myself)
+       {
+         vchild->ppid = myself->pid;
+         vchild->uid = myself->uid;
+         vchild->gid = myself->gid;
+         vchild->pgid = myself->pgid;
+         vchild->sid = myself->sid;
+         vchild->ctty = myself->ctty;
+         vchild->cygstarted = true;
+         vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY);
+       }
       procs[nprocs] = vchild;
       rc = procs[nprocs].wait ();
       if (rc)
@@ -353,6 +356,8 @@ out:
 out1:
   sigproc_printf ("returning %d", rc);
   return rc;
+#undef wval
+#undef vchild
 }
 
 // FIXME: This is inelegant
@@ -566,9 +571,27 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
     sendsig = myself->sendsig;
   else
     {
-      for (int i = 0; !p->dwProcessId && i < 10000; i++)
+      HANDLE dupsig;
+      DWORD dwProcessId;
+      for (int i = 0; !p->sendsig && i < 10000; i++)
        low_priority_sleep (0);
-      HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId);
+      if (p->sendsig)
+       {
+         dupsig = p->sendsig;
+         dwProcessId = p->dwProcessId;
+       }
+      else
+       {
+         dupsig = p->exec_sendsig;
+         dwProcessId = p->exec_dwProcessId;
+       }
+      if (!dupsig)
+       {
+         set_errno (EAGAIN);
+         sigproc_printf ("sendsig handle never materialized");
+         goto out;
+       }
+      HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId);
       if (!hp)
        {
          sigproc_printf ("OpenProcess failed, %E");
@@ -576,14 +599,12 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
          goto out;
        }
       VerifyHandle (hp);
-      for (int i = 0; !p->sendsig && i < 10000; i++)
-       low_priority_sleep (0);
-      if (!DuplicateHandle (hp, p->sendsig, hMainProc, &sendsig, false, 0,
+      if (!DuplicateHandle (hp, dupsig, hMainProc, &sendsig, false, 0,
                            DUPLICATE_SAME_ACCESS) || !sendsig)
        {
-         CloseHandle (hp);
-         sigproc_printf ("DuplicateHandle failed, %E");
          __seterrno ();
+         sigproc_printf ("DuplicateHandle failed, %E");
+         CloseHandle (hp);
          goto out;
        }
       CloseHandle (hp);
@@ -695,17 +716,98 @@ out:
 /* Initialize some of the memory block passed to child processes
    by fork/spawn/exec. */
 
-void __stdcall
-init_child_info (DWORD chtype, child_info *ch, HANDLE subproc_ready)
-{
-  memset (ch, 0, sizeof *ch);
-  ch->cb = chtype == PROC_FORK ? sizeof (child_info_fork) : sizeof (child_info);
-  ch->intro = PROC_MAGIC_GENERIC;
-  ch->magic = CHILD_INFO_MAGIC;
-  ch->type = chtype;
-  ch->subproc_ready = subproc_ready;
-  ch->fhandler_union_cb = sizeof (fhandler_union);
-  ch->user_h = cygwin_user_h;
+child_info::child_info (unsigned in_cb, child_info_types chtype)
+{
+  memset (this, 0, in_cb);
+  cb = in_cb;
+  intro = PROC_MAGIC_GENERIC;
+  magic = CHILD_INFO_MAGIC;
+  type = chtype;
+  fhandler_union_cb = sizeof (fhandler_union);
+  user_h = cygwin_user_h;
+  if (chtype != PROC_SPAWN)
+    subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
+  sigproc_printf ("subproc_ready %p", subproc_ready);
+  if (chtype != PROC_EXEC && myself->wr_proc_pipe != INVALID_HANDLE_VALUE)
+    parent_wr_proc_pipe = myself->wr_proc_pipe;
+}
+
+child_info::~child_info ()
+{
+  if (subproc_ready)
+    CloseHandle (subproc_ready);
+}
+
+child_info_fork::child_info_fork () :
+  child_info (sizeof *this, _PROC_FORK)
+{
+}
+
+child_info_spawn::child_info_spawn (child_info_types chtype) :
+  child_info (sizeof *this, chtype)
+{
+}
+
+void
+child_info::ready (bool execed)
+{
+  if (!subproc_ready)
+    {
+      sigproc_printf ("subproc_ready not set");
+      return;
+    }
+
+  if (!SetEvent (subproc_ready))
+    api_fatal ("SetEvent failed");
+  else
+    sigproc_printf ("signalled %p that I was ready", subproc_ready);
+
+  if (execed)
+    {
+      CloseHandle (subproc_ready);
+      subproc_ready = NULL;
+    }
+}
+
+bool
+child_info::sync (pinfo& vchild, DWORD howlong)
+{
+  if (!subproc_ready)
+    {
+      sigproc_printf ("not waiting.  subproc_ready is NULL");
+      return false;
+    }
+
+  HANDLE w4[2];
+  w4[0] = subproc_ready;
+  w4[1] = vchild.hProcess;
+
+  bool res;
+  sigproc_printf ("waiting for subproc_ready(%p) and child process(%p)", w4[0], w4[1]);
+  switch (WaitForMultipleObjects (2, w4, FALSE, howlong))
+    {
+    case WAIT_OBJECT_0:
+      sigproc_printf ("got subproc_ready for pid %d", vchild->pid);
+      res = true;
+      break;
+    case WAIT_OBJECT_0 + 1:
+      if (WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0)
+       sigproc_printf ("should never happen.  noticed subproc_ready after process exit");
+      else
+       {
+         DWORD exitcode = 0;
+         (void) GetExitCodeProcess (vchild.hProcess, &exitcode);
+         vchild->exitcode = (exitcode & 0xff) << 8;
+         sigproc_printf ("non-cygwin exit value is %p", exitcode);
+       }
+      res = false;
+      break;
+    default:
+      system_printf ("wait failed, pid %d, %E", vchild->pid);
+      res = false;
+      break;
+    }
+  return res;
 }
 
 /* Check the state of all of our children to see if any are stopped or
index 4eb231e..b161b98 100644 (file)
@@ -372,17 +372,15 @@ spawn_guts (const char * prog_arg, const char *const *argv,
 
   STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
 
-  child_info_spawn ciresrv;
-  si.lpReserved2 = (LPBYTE) &ciresrv;
-  si.cbReserved2 = sizeof (ciresrv);
-
-  DWORD chtype;
+  child_info_types chtype;
   if (mode != _P_OVERLAY)
     chtype = PROC_SPAWN;
   else
     chtype = PROC_EXEC;
 
-  init_child_info (chtype, &ciresrv, NULL);
+  child_info_spawn ciresrv (chtype);
+  si.lpReserved2 = (LPBYTE) &ciresrv;
+  si.cbReserved2 = sizeof (ciresrv);
 
   ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
   ciresrv.moreinfo->old_title = NULL;
@@ -616,16 +614,21 @@ spawn_guts (const char * prog_arg, const char *const *argv,
   if (mode == _P_DETACH || !set_console_state_for_spawn ())
     flags |= DETACHED_PROCESS;
 
-  HANDLE saved_sendsig;
+  bool reset_sendsig = false;
   if (mode != _P_OVERLAY)
-    saved_sendsig = NULL;
+    myself->exec_sendsig = NULL;
   else
     {
       /* Reset sendsig so that any process which wants to send a signal
         to this pid will wait for the new process to become active.
         Save the old value in case the exec fails.  */
-      saved_sendsig = myself->sendsig;
-      myself->sendsig = INVALID_HANDLE_VALUE;
+      if (!myself->exec_sendsig)
+       {
+         myself->exec_sendsig = myself->sendsig;
+         myself->exec_dwProcessId = myself->dwProcessId;
+         myself->sendsig = NULL;
+         reset_sendsig = true;
+       }
       /* Save a copy of a handle to the current process around the first time we
         exec so that the pid will not be reused.  Why did I stop cygwin from
         generating its own pids again? */
@@ -636,15 +639,13 @@ spawn_guts (const char * prog_arg, const char *const *argv,
        ProtectHandle (cygheap->pid_handle);
       else
        system_printf ("duplicate to pid_handle failed, %E");
-      ciresrv.parent_wr_proc_pipe = myself->wr_proc_pipe;
     }
 
-  /* Start the process in a suspended state.  Needed so that any potential parent will
-     be able to take notice of the new "execed" process.  This is only really needed
-     to handle exec'ed windows processes since cygwin processes are smart enough that
-     the parent doesn't have to bother but what are you gonna do?  Cygwin lives in
-     a windows world. */
-  if (mode != _P_OVERLAY || !real_path.iscygexec ())
+  /* Some file types (currently only sockets) need extra effort in the parent
+     after CreateProcess and before copying the datastructures to the child.
+     So we have to start the child in suspend state, unfortunately, to avoid
+     a race condition. */
+  if (mode != _P_OVERLAY || cygheap->fdtab.need_fixup_before ())
     flags |= CREATE_SUSPENDED;
 
   const char *runpath = null_app_name ? NULL : (const char *) real_path;
@@ -739,8 +740,11 @@ spawn_guts (const char * prog_arg, const char *const *argv,
       __seterrno ();
       syscall_printf ("CreateProcess failed, %E");
       /* If this was a failed exec, restore the saved sendsig. */
-      if (saved_sendsig)
-       myself->sendsig = saved_sendsig;
+      if (reset_sendsig)
+       {
+         myself->sendsig = myself->exec_sendsig;
+         myself->exec_sendsig = NULL;
+       }
       cygheap_setup_for_child_cleanup (newheap, &ciresrv, 0);
       return -1;
     }
@@ -780,41 +784,32 @@ spawn_guts (const char * prog_arg, const char *const *argv,
                  rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf);
 
   /* Name the handle similarly to proc_subproc. */
-  ProtectHandle1 (pi.hProcess, childhProc);
+  ProtectHandle (pi.hProcess);
 
-  int wait_for_myself = false;
-  DWORD exec_cygstarted;
+  bool wait_for_myself = false;
   if (mode == _P_OVERLAY)
     {
-      if (!real_path.iscygexec ())
-       {
-         /* Store the old exec_cygstarted since this is used as a crude semaphore for
-            detecting when the parent has noticed the change in windows pid for this
-            cygwin pid. */
-         exec_cygstarted = myself->cygstarted;
-         myself->dwProcessId = dwExeced = pi.dwProcessId;  /* Reparenting needs this */
-         myself.alert_parent (__ALERT_REPARENT);
-       }
-      CloseHandle (saved_sendsig);
+      myself->dwProcessId = dwExeced = pi.dwProcessId;
       strace.execing = 1;
-      hExeced = pi.hProcess;
+      myself.hProcess = hExeced = pi.hProcess;
       strcpy (myself->progname, real_path); // FIXME: race?
+      sigproc_printf ("new process name %s", myself->progname);
       close_all_files ();
-      /* If wr_proc_pipe is NULL then this process was not started by a cygwin
-        process.  So, we need to wait around until the process we've just "execed"
-        dies.  Use our own wait facility to wait for our own pid to exit (there
-        is some minor special case code in proc_waiter and friends to accommodate
-        this). */
+      /* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
+       process.  So, we need to wait around until the process we've just "execed"
+       dies.  Use our own wait facility to wait for our own pid to exit (there
+       is some minor special case code in proc_waiter and friends to accommodeate
+       this). */
       if (!myself->wr_proc_pipe)
-       {
-         myself.hProcess = pi.hProcess;
-         myself.remember ();
-         wait_for_myself = true;
-       }
+       {
+        myself.hProcess = pi.hProcess;
+        myself.remember ();
+        wait_for_myself = true;
+        myself->wr_proc_pipe = INVALID_HANDLE_VALUE;
+       }
     }
   else
     {
-      exec_cygstarted = 0;
       myself->set_has_pgid_children ();
       ProtectHandle (pi.hThread);
       pinfo child (cygpid, PID_IN_USE);
@@ -830,8 +825,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
       child.hProcess = pi.hProcess;
       if (!child.remember ())
        {
-         syscall_printf ("process table full");
-         set_errno (EAGAIN);
+         /* FIXME: Child in strange state now. */
+         CloseHandle (pi.hProcess);
+         CloseHandle (pi.hThread);
          res = -1;
          goto out;
        }
@@ -844,222 +840,217 @@ spawn_guts (const char * prog_arg, const char *const *argv,
         However, we should try to find another way to do this eventually. */
       (void) DuplicateHandle (hMainProc, child.shared_handle (), pi.hProcess,
                              NULL, 0, 0, DUPLICATE_SAME_ACCESS);
+      child->start_time = time (NULL); /* Register child's starting time. */
     }
 
-  /* Start the child running */
-  if (flags & CREATE_SUSPENDED)
-    ResumeThread (pi.hThread);
-  ForceCloseHandle (pi.hThread);
-  // ForceCloseHandle (pi.hProcess);  // handled by proc_subproc and friends
+/* Start the child running */
+if (flags & CREATE_SUSPENDED)
+  ResumeThread (pi.hThread);
+ForceCloseHandle (pi.hThread);
 
-  sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
+sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
 
-  if (wait_for_myself)
-    waitpid (myself->pid, &res, 0);
-  else
-    {
-      /* Loop, waiting for parent to notice pid change, if exec_cygstarted.
-         In theory this wait should usually be a no-op.  */
-      if (exec_cygstarted)
-       while (myself->cygstarted == exec_cygstarted && myself.parent_alive ())
-         low_priority_sleep (0);
-      res = 42;
-    }
+if (wait_for_myself)
+  waitpid (myself->pid, &res, 0);
+else
+  ciresrv.sync (myself, INFINITE);
 
-  switch (mode)
-    {
-    case _P_OVERLAY:
-      myself->exit (res, 1);
-      break;
-    case _P_WAIT:
-    case _P_SYSTEM:
-      if (waitpid (cygpid, (int *) &res, 0) != cygpid)
-       res = -1;
-      break;
-    case _P_DETACH:
-      res = 0; /* Lose all memory of this child. */
-      break;
-    case _P_NOWAIT:
-    case _P_NOWAITO:
-    case _P_VFORK:
-      res = cygpid;
-      break;
-    default:
-      break;
-    }
+ForceCloseHandle (pi.hProcess);
+
+switch (mode)
+  {
+  case _P_OVERLAY:
+    myself->exit (res, 1);
+    break;
+  case _P_WAIT:
+  case _P_SYSTEM:
+    if (waitpid (cygpid, (int *) &res, 0) != cygpid)
+      res = -1;
+    break;
+  case _P_DETACH:
+    res = 0;   /* Lose all memory of this child. */
+    break;
+  case _P_NOWAIT:
+  case _P_NOWAITO:
+  case _P_VFORK:
+    res = cygpid;
+    break;
+  default:
+    break;
+  }
 
 out:
-  pthread_cleanup_pop (1);
-  return (int) res;
+pthread_cleanup_pop (1);
+return (int) res;
 }
 
 extern "C" int
 cwait (int *result, int pid, int)
 {
-  return waitpid (pid, result, 0);
+return waitpid (pid, result, 0);
 }
 
 /*
- * Helper function for spawn runtime calls.
- * Doesn't search the path.
- */
+* Helper function for spawn runtime calls.
+* Doesn't search the path.
+*/
 
 extern "C" int
 spawnve (int mode, const char *path, const char *const *argv,
-        const char *const *envp)
+       const char *const *envp)
 {
-  int ret;
+int ret;
 #ifdef NEWVFORK
-  vfork_save *vf = vfork_storage.val ();
+vfork_save *vf = vfork_storage.val ();
 
-  if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
-    mode = _P_NOWAIT;
-  else
-    vf = NULL;
+if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
+  mode = _P_NOWAIT;
+else
+  vf = NULL;
 #endif
 
-  syscall_printf ("spawnve (%s, %s, %x)", path, argv[0], envp);
+syscall_printf ("spawnve (%s, %s, %x)", path, argv[0], envp);
 
-  switch (mode)
-    {
-    case _P_OVERLAY:
-      /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
-      /* Just act as an exec if _P_OVERLAY set. */
-      spawn_guts (path, argv, envp, mode);
-      /* Errno should be set by spawn_guts.  */
-      ret = -1;
-      break;
-    case _P_VFORK:
-    case _P_NOWAIT:
-    case _P_NOWAITO:
-    case _P_WAIT:
-    case _P_DETACH:
-    case _P_SYSTEM:
-      ret = spawn_guts (path, argv, envp, mode);
+switch (mode)
+  {
+  case _P_OVERLAY:
+    /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
+    /* Just act as an exec if _P_OVERLAY set. */
+    spawn_guts (path, argv, envp, mode);
+    /* Errno should be set by spawn_guts.  */
+    ret = -1;
+    break;
+  case _P_VFORK:
+  case _P_NOWAIT:
+  case _P_NOWAITO:
+  case _P_WAIT:
+  case _P_DETACH:
+  case _P_SYSTEM:
+    ret = spawn_guts (path, argv, envp, mode);
 #ifdef NEWVFORK
-      if (vf)
-       {
-         if (ret > 0)
-           {
-             debug_printf ("longjmping due to vfork");
-             vf->restore_pid (ret);
-           }
-       }
+    if (vf)
+      {
+       if (ret > 0)
+         {
+           debug_printf ("longjmping due to vfork");
+           vf->restore_pid (ret);
+         }
+      }
 #endif
-      break;
-    default:
-      set_errno (EINVAL);
-      ret = -1;
-      break;
-    }
-  return ret;
+    break;
+  default:
+    set_errno (EINVAL);
+    ret = -1;
+    break;
+  }
+return ret;
 }
 
 /*
- * spawn functions as implemented in the MS runtime library.
- * Most of these based on (and copied from) newlib/libc/posix/execXX.c
- */
+* spawn functions as implemented in the MS runtime library.
+* Most of these based on (and copied from) newlib/libc/posix/execXX.c
+*/
 
 extern "C" int
 spawnl (int mode, const char *path, const char *arg0, ...)
 {
-  int i;
-  va_list args;
-  const char *argv[256];
+int i;
+va_list args;
+const char *argv[256];
 
-  va_start (args, arg0);
-  argv[0] = arg0;
-  i = 1;
+va_start (args, arg0);
+argv[0] = arg0;
+i = 1;
 
-  do
-      argv[i] = va_arg (args, const char *);
-  while (argv[i++] != NULL);
+do
+    argv[i] = va_arg (args, const char *);
+while (argv[i++] != NULL);
 
-  va_end (args);
+va_end (args);
 
-  return spawnve (mode, path, (char * const  *) argv, cur_environ ());
+return spawnve (mode, path, (char * const  *) argv, cur_environ ());
 }
 
 extern "C" int
 spawnle (int mode, const char *path, const char *arg0, ...)
 {
-  int i;
-  va_list args;
-  const char * const *envp;
-  const char *argv[256];
+int i;
+va_list args;
+const char * const *envp;
+const char *argv[256];
 
-  va_start (args, arg0);
-  argv[0] = arg0;
-  i = 1;
+va_start (args, arg0);
+argv[0] = arg0;
+i = 1;
 
-  do
-    argv[i] = va_arg (args, const char *);
-  while (argv[i++] != NULL);
+do
+  argv[i] = va_arg (args, const char *);
+while (argv[i++] != NULL);
 
-  envp = va_arg (args, const char * const *);
-  va_end (args);
+envp = va_arg (args, const char * const *);
+va_end (args);
 
-  return spawnve (mode, path, (char * const *) argv, (char * const *) envp);
+return spawnve (mode, path, (char * const *) argv, (char * const *) envp);
 }
 
 extern "C" int
 spawnlp (int mode, const char *path, const char *arg0, ...)
 {
-  int i;
-  va_list args;
-  const char *argv[256];
+int i;
+va_list args;
+const char *argv[256];
 
-  va_start (args, arg0);
-  argv[0] = arg0;
-  i = 1;
+va_start (args, arg0);
+argv[0] = arg0;
+i = 1;
 
-  do
-      argv[i] = va_arg (args, const char *);
-  while (argv[i++] != NULL);
+do
+    argv[i] = va_arg (args, const char *);
+while (argv[i++] != NULL);
 
-  va_end (args);
+va_end (args);
 
-  return spawnvpe (mode, path, (char * const *) argv, cur_environ ());
+return spawnvpe (mode, path, (char * const *) argv, cur_environ ());
 }
 
 extern "C" int
 spawnlpe (int mode, const char *path, const char *arg0, ...)
 {
-  int i;
-  va_list args;
-  const char * const *envp;
-  const char *argv[256];
+int i;
+va_list args;
+const char * const *envp;
+const char *argv[256];
 
-  va_start (args, arg0);
-  argv[0] = arg0;
-  i = 1;
+va_start (args, arg0);
+argv[0] = arg0;
+i = 1;
 
-  do
-    argv[i] = va_arg (args, const char *);
-  while (argv[i++] != NULL);
+do
+  argv[i] = va_arg (args, const char *);
+while (argv[i++] != NULL);
 
-  envp = va_arg (args, const char * const *);
-  va_end (args);
+envp = va_arg (args, const char * const *);
+va_end (args);
 
-  return spawnvpe (mode, path, (char * const *) argv, envp);
+return spawnvpe (mode, path, (char * const *) argv, envp);
 }
 
 extern "C" int
 spawnv (int mode, const char *path, const char * const *argv)
 {
-  return spawnve (mode, path, argv, cur_environ ());
+return spawnve (mode, path, argv, cur_environ ());
 }
 
 extern "C" int
 spawnvp (int mode, const char *path, const char * const *argv)
 {
-  return spawnvpe (mode, path, argv, cur_environ ());
+return spawnvpe (mode, path, argv, cur_environ ());
 }
 
 extern "C" int
 spawnvpe (int mode, const char *file, const char * const *argv,
-                                            const char * const *envp)
+                                          const char * const *envp)
 {
-  path_conv buf;
-  return spawnve (mode, find_exec (file, buf), argv, envp);
+path_conv buf;
+return spawnve (mode, find_exec (file, buf), argv, envp);
 }