OSDN Git Service

* cygheap.cc (cygheap_fixup_in_child): Don't page round cygheap copied from
authorcgf <cgf>
Sat, 14 Oct 2000 05:52:38 +0000 (05:52 +0000)
committercgf <cgf>
Sat, 14 Oct 2000 05:52:38 +0000 (05:52 +0000)
parent.
* dcrt0.cc (do_exit): Don't cleanup pinfo on exit.  That happens automatically
now.
* exceptions.cc (signal_exit): Ditto.
* fork.cc (fork_parent): Use stack_here value passed in from fork().
(fork): Figure out top of stack here and pass it to fork_parent.
* pinfo.cc (_pinfo::record_death): Eliminate.
* pinfo.h (_pinfo): Ditto.
* sigproc.cc (proc_exists): Simplify.
(proc_terminate): Ditto.
(remove_zombie): Don't cleanup pinfo stuff.
(wait_sig): Send subproc_ready signal whether execed or spawned.
* spawn.cc (spawn_guts): Always create subproc_ready event.  Use it for both
exec and spawn.
(_spawnve): Send proper mode to spawn_guts when mode != _P_OVERLAY.

winsup/cygwin/ChangeLog
winsup/cygwin/cygheap.cc
winsup/cygwin/dcrt0.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/fork.cc
winsup/cygwin/pinfo.cc
winsup/cygwin/pinfo.h
winsup/cygwin/sigproc.cc
winsup/cygwin/spawn.cc

index c4bd8f3..e0f8811 100644 (file)
@@ -1,3 +1,22 @@
+Sat Oct 14 01:45:25 2000  Christopher Faylor <cgf@cygnus.com>
+
+       * cygheap.cc (cygheap_fixup_in_child): Don't page round cygheap copied
+       from parent.
+       * dcrt0.cc (do_exit): Don't cleanup pinfo on exit.  That happens
+       automatically now.
+       * exceptions.cc (signal_exit): Ditto.
+       * fork.cc (fork_parent): Use stack_here value passed in from fork().
+       (fork): Figure out top of stack here and pass it to fork_parent.
+       * pinfo.cc (_pinfo::record_death): Eliminate.
+       * pinfo.h (_pinfo): Ditto.
+       * sigproc.cc (proc_exists): Simplify.
+       (proc_terminate): Ditto.
+       (remove_zombie): Don't cleanup pinfo stuff.
+       (wait_sig): Send subproc_ready signal whether execed or spawned.
+       * spawn.cc (spawn_guts): Always create subproc_ready event.  Use it for
+       both exec and spawn.
+       (_spawnve): Send proper mode to spawn_guts when mode != _P_OVERLAY.
+
 Thu Oct 12 23:11:05 2000  Christopher Faylor <cgf@cygnus.com>
 
        * dtable.cc (dtable::fixup_after_fork): Revert thinko below.
index ee686fa..21bde12 100644 (file)
@@ -207,9 +207,7 @@ cygheap_fixup_in_child (HANDLE parent, bool execed)
 
   /* Copy memory from the parent */
   m = 0;
-  n = (DWORD) pagetrunc (n + 4095);
-  if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) ||
-      m != n)
+  if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) || m != n)
     api_fatal ("Couldn't read parent's cygwin heap %d bytes != %d, %E",
               n, m);
 
index 4c8b428..7177506 100644 (file)
@@ -973,7 +973,6 @@ enum
 extern "C" void __stdcall
 do_exit (int status)
 {
-  BOOL cleanup_pinfo;
   UINT n = (UINT) status;
   static int NO_COPY exit_state = 0;
 
@@ -1013,10 +1012,7 @@ do_exit (int status)
     }
 
   if (n & EXIT_REPARENTING)
-    {
-      n &= ~EXIT_REPARENTING;
-      cleanup_pinfo = FALSE;
-    }
+    n &= ~EXIT_REPARENTING;
   else
     {
       myself->stopsig = 0;
@@ -1045,7 +1041,6 @@ do_exit (int status)
        }
 
       tty_terminate ();
-      cleanup_pinfo = TRUE;
     }
 
   window_terminate ();
@@ -1060,11 +1055,6 @@ do_exit (int status)
       ForceCloseHandle1 (hExeced, childhProc);
     }
 
-  if (cleanup_pinfo)
-    myself->record_death ();
-  else
-    sigproc_printf ("not cleanup_pinfo");
-
   shared_terminate ();
 
   sigproc_printf ("calling ExitProcess %d", n);
@@ -1106,7 +1096,6 @@ __api_fatal (const char *fmt, ...)
   /* We are going down without mercy.  Make sure we reset
      our process_state. */
   sigproc_terminate ();
-  myself->record_death ();
 #ifdef DEBUGGING
   (void) try_to_debug ();
 #endif
index 6f838ee..8d81780 100644 (file)
@@ -1005,11 +1005,7 @@ signal_exit (int rc)
 {
   rc = EXIT_SIGNAL | (rc << 8);
   if (exit_already++)
-    {
-      /* We are going down - reset our process_state without locking. */
-      myself->record_death ();
-      ExitProcess (rc);
-    }
+    ExitProcess (rc);
 
   /* We'd like to stop the main thread from executing but when we do that it
      causes random, inexplicable hangs.  So, instead, we set up the priority
index 8204779..a02e88b 100644 (file)
@@ -308,10 +308,9 @@ debug_printf ("hParent %p", hParent);
 }
 
 static int __stdcall
-fork_parent (HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork &ch)
+fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork &ch)
 {
   HANDLE subproc_ready, forker_finished;
-  void *stack_here = &hParent;
   DWORD rc;
   PROCESS_INFORMATION pi = {0, NULL, 0, 0};
   static NO_COPY HANDLE last_fork_proc = NULL;
@@ -339,8 +338,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork
                                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                                       NULL);
 
-  syscall_printf ("CreateProcessA (%s, %s,0,0,1,%x, 0,0,%p,%p)",
-                 myself->progname, myself->progname, c_flags, &si, &pi);
   if (console_handle != INVALID_HANDLE_VALUE && console_handle != 0)
     CloseHandle (console_handle);
   else
@@ -407,16 +404,18 @@ fork_parent (HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork
   ch.cygheap_max = cygheap_max;
 
   char sa_buf[1024];
-  rc = CreateProcessA (myself->progname, /* image to run */
-                      myself->progname, /* what we send in arg0 */
-                      allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
-                      allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
-                      TRUE,      /* inherit handles from parent */
-                      c_flags,
-                      NULL,      /* environment filled in later */
-                      0,                 /* use current drive/directory */
-                      &si,
-                      &pi);
+  syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
+                 myself->progname, myself->progname, c_flags, &si, &pi);
+  rc = CreateProcess (myself->progname, /* image to run */
+                     myself->progname, /* what we send in arg0 */
+                     allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
+                     allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
+                     TRUE,       /* inherit handles from parent */
+                     c_flags,
+                     NULL,       /* environment filled in later */
+                     0,                  /* use current drive/directory */
+                     &si,
+                     &pi);
 
   CloseHandle (hParent);
 
@@ -579,14 +578,11 @@ fork ()
     bool load_dlls;
   } grouped;
 
-  int res;
-  int x;
-
   MALLOC_CHECK;
 
-  // grow_stack_slack ();
-
   debug_printf ("entering");
+  grouped.hParent = grouped.first_dll = NULL;
+  grouped.load_dlls = 0;
 
   if (ISSTATE(myself, PID_SPLIT_HEAP))
     {
@@ -597,13 +593,17 @@ fork ()
       return -1;
     }
 
+  void *esp;
+  __asm ("movl %%esp,%0": "=r" (esp));
+
   child_info_fork ch;
-  x = setjmp (ch.jmp);
 
-  if (x != 0)
+  int res = setjmp (ch.jmp);
+
+  if (res)
     res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls);
   else
-    res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, ch);
+    res = fork_parent (esp, grouped.hParent, grouped.first_dll, grouped.load_dlls, ch);
 
   MALLOC_CHECK;
   syscall_printf ("%d = fork()", res);
index f14b45c..68f4923 100644 (file)
@@ -175,17 +175,6 @@ _pinfo::copysigs(_pinfo *_other)
 }
 
 void
-_pinfo::record_death ()
-{
-  /* CGF FIXME - needed? */
-  if (dwProcessId == GetCurrentProcessId () && !my_parent_is_alive ())
-    {
-      process_state = PID_NOT_IN_USE;
-      hProcess = NULL;
-    }
-}
-
-void
 pinfo::init (pid_t n, DWORD create, HANDLE in_h)
 {
   if (n == myself->pid)
index 2c5b862..bb1f2fe 100644 (file)
@@ -119,8 +119,6 @@ private:
 public:
   /* Pointer to mmap'ed areas for this process.  Set up by fork. */
   void *mmap_ptr;
-
-  void record_death ();
 };
 
 class pinfo
index a2b01cc..675feb4 100644 (file)
@@ -205,48 +205,8 @@ proc_exists (_pinfo *p)
 
   if (p == NULL)
     return FALSE;
-
-  if (p == myself || p == myself_nowait_nonmain || p == myself_nowait)
+  else
     return TRUE;
-
-  if (p->process_state == PID_NOT_IN_USE || !p->dwProcessId)
-    return FALSE;
-
-  sigproc_printf ("checking for existence of pid %d, window pid %d", p->pid,
-             p->dwProcessId);
-  if (p->ppid == myself->pid && p->hProcess != NULL)
-    {
-      sigproc_printf ("it's mine, process_state %x", p->process_state);
-      return proc_can_be_signalled (p);
-    }
-
-  /* Note: Process is alive if OpenProcess() call fails due to permissions */
-  if (((h = OpenProcess (STANDARD_RIGHTS_REQUIRED, FALSE, p->dwProcessId))
-      != NULL) || (GetLastError () == ERROR_ACCESS_DENIED))
-    {
-      sigproc_printf ("it exists, %p", h);
-      if (h)
-       {
-         DWORD rc = WaitForSingleObject (h, 0);
-         CloseHandle (h);
-         if (rc == WAIT_OBJECT_0)
-           return 0;
-       }
-      return proc_can_be_signalled (p);
-    }
-
-  sigproc_printf ("it doesn't exist");
-#if 0
-  /* If the parent pid does not exist, clean this process out of the pinfo
-   * table.  It must have died abnormally.
-   */
-  if ((p->pid == p->ppid) || (p->ppid == 1) || !pid_exists (p->ppid))
-    {
-      p->hProcess = NULL;
-      p->process_state = PID_NOT_IN_USE;
-    }
-#endif
-  return FALSE;
 }
 
 /* Return 1 if this is one of our children, zero otherwise.
@@ -500,22 +460,13 @@ proc_terminate (void)
          else
            {
              ForceCloseHandle1 (pchildren[i]->hProcess, childhProc);
-             if (!proc_exists (pchildren[i]))
-               {
-                 sigproc_printf ("%d(%d) doesn't exist", pchildren[i]->pid,
+             sigproc_printf ("%d(%d) closed child handle", pchildren[i]->pid,
                              pchildren[i]->dwProcessId);
-                 pchildren[i]->process_state = PID_NOT_IN_USE; /* a reaped child  CGF FIXME -- still needed? */
-               }
-             else
-               {
-                 sigproc_printf ("%d(%d) closing active child handle", pchildren[i]->pid,
-                             pchildren[i]->dwProcessId);
-                 pchildren[i]->ppid = 1;
-                 if (pchildren[i]->pgid == myself->pid)
-                   pchildren[i]->process_state |= PID_ORPHANED;
-               }
+             pchildren[i]->ppid = 1;
+             if (pchildren[i]->pgid == myself->pid)
+               pchildren[i]->process_state |= PID_ORPHANED;
            }
-         pchildren[i].release (); // FIXME: this breaks older gccs for some reason
+         pchildren[i].release ();
        }
       nchildren = nzombies = 0;
 
@@ -601,6 +552,7 @@ sigproc_init ()
   /* local event signaled when main thread has been dispatched
      to a signal handler function. */
   signal_arrived = CreateEvent(&sec_none_nih, TRUE, FALSE, NULL);
+  ProtectHandle (signal_arrived);
 
   if (!(hwait_sig = makethread (wait_sig, NULL, 0, "sig")))
     {
@@ -669,14 +621,6 @@ sigproc_terminate (void)
            WaitForSingleObject (h, 10000);
          ForceCloseHandle1 (h, hwait_sig);
 
-         /* Exiting thread.  Cleanup.  Don't set to inactive if a child has been
-            execed with the same pid. */
-         if (!myself->dwProcessId || myself->dwProcessId == GetCurrentProcessId ())
-           myself->process_state &= ~PID_ACTIVE;
-         else
-           sigproc_printf ("Did not clear PID_ACTIVE since %d != %d",
-                       myself->dwProcessId, GetCurrentProcessId ());
-
          /* In case of a sigsuspend */
          SetEvent (signal_arrived);
 
@@ -1052,7 +996,6 @@ remove_zombie (int ci)
     {
       ForceCloseHandle1 (zombies[ci]->hProcess, childhProc);
       ForceCloseHandle1 (zombies[ci]->pid_handle, pid_handle);
-      zombies[ci]->process_state = PID_NOT_IN_USE;     /* a reaped child */
       zombies[ci].release ();
     }
 
@@ -1184,7 +1127,8 @@ wait_sig (VOID *)
    * windows process waiting to see if it's started a cygwin process or not.
    * Signalling subproc_ready indicates that we are a cygwin process.
    */
-  if (child_proc_info && child_proc_info->type == PROC_EXEC)
+  if (child_proc_info &&
+      (child_proc_info->type == PROC_FORK || child_proc_info->type == PROC_SPAWN))
     {
       debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
       if (!SetEvent (child_proc_info->subproc_ready))
@@ -1383,6 +1327,7 @@ WFSO (HANDLE hHandle, DWORD dwMilliseconds)
   DWORD ret;
   sigframe thisframe (mainthread);
   ret = WaitForSingleObject (hHandle, dwMilliseconds);
+if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds);
   return ret;
 }
 
@@ -1394,6 +1339,7 @@ WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds
   DWORD ret;
   sigframe thisframe (mainthread);
   ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds);
+if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds);
   return ret;
 }
 }
index adf5b1f..0aab714 100644 (file)
@@ -158,21 +158,6 @@ handle (int n, int direction)
   return fh->get_output_handle ();
 }
 
-/* Cover function for CreateProcess.
-
-   This function is used by both the routines that search $PATH and those
-   that do not.  This should work out ok as according to the documentation,
-   CreateProcess only searches $PATH if PROG has no directory elements.
-
-   Spawning doesn't fit well with Posix's fork/exec (one can argue the merits
-   of either but that's beside the point).  If we're exec'ing we want to
-   record the child pid for fork.  If we're spawn'ing we don't want to do
-   this.  It is up to the caller to handle both cases.
-
-   The result is the process id.  The handle of the created process is
-   stored in H.
-*/
-
 HANDLE NO_COPY hExeced = NULL;
 
 int
@@ -252,7 +237,7 @@ public:
   int argc;
   av (int ac, const char * const *av) : calloced (0), argc (ac)
   {
-    argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 1) * sizeof (char *));
+    argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 5) * sizeof (char *));
     memcpy (argv, av, (argc + 1) * sizeof (char *));
   }
   ~av ()
@@ -348,16 +333,14 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
   si.lpReserved2 = (LPBYTE) &ciresrv;
   si.cbReserved2 = sizeof (ciresrv);
 
-  HANDLE spr = NULL;
   DWORD chtype;
   if (mode != _P_OVERLAY && mode != _P_VFORK)
     chtype = PROC_SPAWN;
   else
-    {
-      spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
-      ProtectHandle (spr);
-      chtype = PROC_EXEC;
-    }
+    chtype = PROC_EXEC;
+
+  HANDLE spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
+  ProtectHandle (spr);
 
   init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
   if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &ciresrv.parent, 0, 1,
@@ -555,8 +538,6 @@ skip_arg_parsing:
   si.hStdError = handle (2, 1); /* Get output handle */
   si.cb = sizeof (si);
 
-  /* Pass fd table to a child */
-
   syscall_printf ("spawn_guts (%s, %.132s)", (char *) real_path, one_line.buf);
 
   int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED |
@@ -696,8 +677,6 @@ skip_arg_parsing:
   if (mode == _P_OVERLAY)
     {
       strcpy (myself->progname, real_path);
-      // close_all_files ();
-      proc_terminate ();
       hExeced = pi.hProcess;
       myself->dwProcessId = pi.dwProcessId;
 
@@ -765,127 +744,123 @@ skip_arg_parsing:
     CloseHandle (hToken);
 
   DWORD res;
+  BOOL exited;
 
-  if (mode == _P_OVERLAY || mode == _P_VFORK)
-    {
-      BOOL exited;
-
-      HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr};
-      int nwait = 3;
+  HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr};
+  int nwait = 3;
 
-      SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
-      res = 0;
-      exited = FALSE;
-      MALLOC_CHECK;
-      for (int i = 0; i < 100; i++)
+  res = 0;
+  exited = FALSE;
+  MALLOC_CHECK;
+  for (int i = 0; i < 100; i++)
+    {
+      switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
        {
-         switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
+       case WAIT_OBJECT_0:
+         sigproc_printf ("subprocess exited");
+         DWORD exitcode;
+         if (!GetExitCodeProcess (pi.hProcess, &exitcode))
+           exitcode = 1;
+         res |= exitcode;
+         exited = TRUE;
+
+         if (nwait > 2 && !(res & EXIT_REPARENTING) &&
+             (mode == _P_OVERLAY || mode == _P_VFORK))
+           res |= EXIT_REPARENTING;
+         break;
+       case WAIT_OBJECT_0 + 1:
+         sigproc_printf ("signal arrived");
+         ResetEvent (signal_arrived);
+         continue;
+       case WAIT_OBJECT_0 + 2:
+         if (mode == _P_OVERLAY)
            {
-           case WAIT_OBJECT_0:
-             sigproc_printf ("subprocess exited");
-             DWORD exitcode;
-             if (!GetExitCodeProcess (pi.hProcess, &exitcode))
-               exitcode = 1;
-             res |= exitcode;
-             exited = TRUE;
-
-             if (nwait <= 2 || (res & EXIT_REPARENTING) || (mode != _P_OVERLAY && mode != _P_VFORK))
-               /* nothing to do */;
-             else if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
-               goto reparent;
-             break;
-           case WAIT_OBJECT_0 + 1:
-             sigproc_printf ("signal arrived");
-             ResetEvent (signal_arrived);
-             continue;
-           case WAIT_OBJECT_0 + 2:
-             if (mode == _P_OVERLAY)
+             res |= EXIT_REPARENTING;
+             if (!parent_alive)
                {
-             reparent:
-                 res |= EXIT_REPARENTING;
-                 if (!parent_alive)
-                   {
-                     nwait = 1;
-                     sigproc_terminate ();
-                     continue;
-                   }
+                 nwait = 1;
+                 sigproc_terminate ();
+                 continue;
                }
-             break;
-           case WAIT_FAILED:
-             DWORD r;
-             system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
-                            nwait, myself->pid, myself->dwProcessId);
-             system_printf ("waitbuf[0] %p %d", waitbuf[0],
-                            GetHandleInformation (waitbuf[0], &r));
-             system_printf ("waitbuf[1] %p = %d", waitbuf[1],
-                            GetHandleInformation (waitbuf[1], &r));
-             set_errno (ECHILD);
-             return -1;
            }
          break;
+       case WAIT_FAILED:
+         system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
+                        nwait, myself->pid, myself->dwProcessId);
+         system_printf ("waitbuf[0] %p %d", waitbuf[0],
+                        WaitForSingleObject (waitbuf[0], 0));
+         system_printf ("waitbuf[1] %p = %d", waitbuf[1],
+                        WaitForSingleObject (waitbuf[1], 0));
+         system_printf ("waitbuf[w] %p = %d", waitbuf[2],
+                        WaitForSingleObject (waitbuf[2], 0));
+         set_errno (ECHILD);
+         try_to_debug ();
+         return -1;
        }
+      break;
+    }
 
-      ForceCloseHandle (spr);
+  ForceCloseHandle (spr);
 
-      sigproc_printf ("res = %x", res);
+  sigproc_printf ("res = %x", res);
 
-      if (res & EXIT_REPARENTING)
+  if (mode == _P_OVERLAY && (res & EXIT_REPARENTING))
+    {
+      /* Try to reparent child process.
+       * Make handles to child available to parent process and exit with
+       * EXIT_REPARENTING status. Wait() syscall in parent will then wait
+       * for newly created child.
+       */
+      pinfo parent (myself->ppid);
+      if (!parent)
+       /* nothing */;
+      else
        {
-         /* Try to reparent child process.
-          * Make handles to child available to parent process and exit with
-          * EXIT_REPARENTING status. Wait() syscall in parent will then wait
-          * for newly created child.
-          */
-         pinfo parent (myself->ppid);
-         if (!parent)
-           /* nothing */;
-         else
+         int rc = 0;
+         HANDLE oldh = myself->hProcess;
+         HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
+                                 parent->dwProcessId);
+         sigproc_printf ("parent handle %p, pid %d", h, parent->dwProcessId);
+         if (h == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
+           rc = 1;
+         else if (h)
            {
-             int rc = 0;
-             HANDLE oldh = myself->hProcess;
-             HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
-                                     parent->dwProcessId);
-             sigproc_printf ("parent handle %p, pid %d", h, parent->dwProcessId);
-             if (h == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
-               rc = 1;
-             else if (h)
-               {
-                 ProtectHandle (h);
-                 rc = DuplicateHandle (hMainProc, pi.hProcess,
-                                       h, &myself->hProcess, 0, FALSE,
-                                       DUPLICATE_SAME_ACCESS);
-                 sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p",
-                                 rc, oldh, myself->hProcess);
-                 ForceCloseHandle (h);
-               }
-             if (!rc)
-               {
-                 system_printf ("Reparent failed, parent handle %p, %E", h);
-                 system_printf ("my dwProcessId %d, myself->dwProcessId %d",
-                                GetCurrentProcessId(), myself->dwProcessId);
-                 system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess);
-               }
+             ProtectHandle (h);
+             rc = DuplicateHandle (hMainProc, pi.hProcess,
+                                   h, &myself->hProcess, 0, FALSE,
+                                   DUPLICATE_SAME_ACCESS);
+             sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p",
+                             rc, oldh, myself->hProcess);
+             ForceCloseHandle (h);
            }
-         if (hExeced)
+         if (!rc)
            {
-             ForceCloseHandle1 (hExeced, childhProc);
-             hExeced = INVALID_HANDLE_VALUE;
-             close_all_files ();
+             system_printf ("Reparent failed, parent handle %p, %E", h);
+             system_printf ("my dwProcessId %d, myself->dwProcessId %d",
+                            GetCurrentProcessId(), myself->dwProcessId);
+             system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess);
            }
        }
-      else if (exited)
+      if (hExeced)
        {
          ForceCloseHandle1 (hExeced, childhProc);
-         hExeced = INVALID_HANDLE_VALUE; // stop do_exit from attempting to terminate child
+         hExeced = INVALID_HANDLE_VALUE;
        }
-
-      MALLOC_CHECK;
-      if (mode == _P_OVERLAY)
-       ExitProcess (res);
     }
+  else if (exited)
+    {
+      ForceCloseHandle1 (hExeced, childhProc);
+      hExeced = INVALID_HANDLE_VALUE; // stop do_exit from attempting to terminate child
+    }
+
+  MALLOC_CHECK;
 
   switch (mode)
     {
+    case _P_OVERLAY:
+      proc_terminate ();
+      ExitProcess (0);
+      break;
     case _P_WAIT:
       waitpid (cygpid, (int *) &res, 0);
       break;
@@ -945,7 +920,7 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
     case _P_WAIT:
     case _P_DETACH:
       subproc_init ();
-      ret = spawn_guts (hToken, path, argv, envp, 0);
+      ret = spawn_guts (hToken, path, argv, envp, mode);
       if (vf && ret > 0)
        {
          vf->pid = ret;