From 6daf4afb11869add20516ef4ae451898840f1ffa Mon Sep 17 00:00:00 2001
From: Christopher Faylor <me@cgf.cx>
Date: Wed, 21 Mar 2012 05:23:13 +0000
Subject: [PATCH] * child_info.h: Reset magic number.
 (child_info_spawn::wait_for_myself): Move function to sigproc.cc. * pinfo.cc
 (is_toplevel_proc): Delete unneeded variable. * sigproc.cc
 (child_info_spawn::wait_for_myself): Move function from header to here.  Do
 all setup required to properly wait for top-level execed process to exit. *
 spawn.cc (child_info_spawn::worker): Attempt to properly handle _P_DETACH.
 Set wr_proc_pipe if top-level process even when execing.  Just call
 wait_for_myself() to...  wait for myself.  Don't call cleanup twice.

---
 winsup/cygwin/ChangeLog    | 13 +++++++++++++
 winsup/cygwin/child_info.h |  4 ++--
 winsup/cygwin/pinfo.cc     |  2 --
 winsup/cygwin/sigproc.cc   | 10 ++++++++++
 winsup/cygwin/spawn.cc     | 16 ++++++----------
 5 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index faed3729b..042ff815c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,16 @@
+2012-03-21  Christopher Faylor  <me.cygwin2012@cgf.cx>
+
+	* child_info.h: Reset magic number.
+	(child_info_spawn::wait_for_myself): Move function to sigproc.cc.
+	* pinfo.cc (is_toplevel_proc): Delete unneeded variable.
+	* sigproc.cc (child_info_spawn::wait_for_myself): Move function from
+	header to here.  Do all setup required to properly wait for top-level
+	execed process to exit.
+	* spawn.cc (child_info_spawn::worker): Attempt to properly handle
+	_P_DETACH.  Set wr_proc_pipe if top-level process even when execing.
+	Just call wait_for_myself() to...  wait for myself.  Don't call cleanup
+	twice.
+
 2012-03-21  Christopher Faylor  <me.cygwin2012@cgf.cx>
 
 	* pinfo.cc (proc_waiter): Remove debugging.
diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index 8d1d4e906..981222032 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -35,7 +35,7 @@ enum child_status
 #define EXEC_MAGIC_SIZE sizeof(child_info)
 
 /* Change this value if you get a message indicating that it is out-of-sync. */
-#define CURR_CHILD_INFO_MAGIC 0xa49e665eU
+#define CURR_CHILD_INFO_MAGIC 0x4a52da7eU
 
 #define NPROCS	256
 
@@ -158,7 +158,7 @@ public:
 	return true;
       }
   }
-  void wait_for_myself () { WaitForSingleObject (ev, INFINITE); }
+  void wait_for_myself ();
   bool has_execed () const
   {
     if (hExeced)
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 737cff4fb..a13100cfc 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -49,8 +49,6 @@ pinfo_basic myself_initial NO_COPY;
 
 pinfo NO_COPY myself (static_cast<_pinfo *> (&myself_initial));	// Avoid myself != NULL checks
 
-bool is_toplevel_proc;
-
 /* Setup the pinfo structure for this process.  There may already be a
    _pinfo for this "pid" if h != NULL. */
 
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 78281792f..967a97e3a 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -911,6 +911,16 @@ cygheap_exec_info::alloc ()
 					     + (nprocs * sizeof (children[0])));
 }
 
+void
+child_info_spawn::wait_for_myself ()
+{
+  myself.set_rd_proc_pipe (rd_proc_pipe);
+  ForceCloseHandle (wr_proc_pipe);
+  wr_proc_pipe = NULL;
+  myself.remember (false);
+  WaitForSingleObject (ev, INFINITE);
+}
+
 void
 child_info::cleanup ()
 {
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index f5501a540..f3d917aed 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -614,10 +614,12 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
     c_flags |= CREATE_NEW_PROCESS_GROUP;
   refresh_cygheap ();
 
-  if (chtype == _CH_EXEC)
-    wr_proc_pipe = my_wr_proc_pipe;
-  else
+  if (mode == _P_DETACH)
+    /* all set */;
+  else if (chtype != _CH_EXEC || !my_wr_proc_pipe)
     prefork ();
+  else
+    wr_proc_pipe = my_wr_proc_pipe;
 
   /* When ruid != euid we create the new process under the current original
      account and impersonate in child, this way maintaining the different
@@ -853,14 +855,8 @@ loop:
 	  close_all_files (true);
 	  if (!my_wr_proc_pipe
 	      && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
-	    {
-	      extern bool is_toplevel_proc;
-	      is_toplevel_proc = true;
-	      myself.remember (false);
-	      wait_for_myself ();
-	    }
+	    wait_for_myself ();
 	}
-      this->cleanup ();
       myself.exit (EXITCODE_NOSET);
       break;
     case _P_WAIT: