[newlib-cygwin] Cygwin: fix child getting another pid after spawnve

Corinna Vinschen corinna@sourceware.org
Fri Feb 8 14:50:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=88605243a19bbc2b6b9be36b99f513140b972e38

commit 88605243a19bbc2b6b9be36b99f513140b972e38
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Fri Feb 8 15:49:47 2019 +0100

    Cygwin: fix child getting another pid after spawnve
    
    When calling spawnve, in contrast to execve, the parent has
    to create the pid for the child.  With the old technique
    this was simply the Windows pid, but now we have to inform
    the child about its new pid.
    
    Add a cygpid member to class child_info_spawn.  Set it in
    child_info_spawn::worker, just prior to calling CreateProcess
    rather than afterwards.  Overwrite cygheap->pid in
    child_info_spawn::handle_spawn before calling pinfo::thisproc.
    Make sure pinfo::thisproc knows the pid is already set by
    setting the handle argument to INVALID_HANDLE_VALUE.
    
    Also set procinfo->dwProcessId to myself_initial.dwProcessId
    instead of to myself_initial.pid for clarity.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/child_info.h | 1 +
 winsup/cygwin/dcrt0.cc     | 7 ++++++-
 winsup/cygwin/pinfo.cc     | 9 +++++++--
 winsup/cygwin/spawn.cc     | 8 ++------
 4 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index 6726411..847614f 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -144,6 +144,7 @@ class child_info_spawn: public child_info
 {
   HANDLE hExeced;
   HANDLE ev;
+  pid_t cygpid;
 public:
   cygheap_exec_info *moreinfo;
   int __stdin;
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 78506d4..11edcdf 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -652,11 +652,16 @@ child_info_spawn::handle_spawn ()
 	cygheap_fixup_in_child (true);
 	memory_init ();
       }
+
+  cygheap->pid = cygpid;
+
+  /* Spawned process sets h to INVALID_HANDLE_VALUE to notify
+     pinfo::thisproc not to create another pid. */
   if (!moreinfo->myself_pinfo ||
       !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
 			GetCurrentProcess (), &h, 0,
 			FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
-    h = NULL;
+    h = (type == _CH_SPAWN) ? INVALID_HANDLE_VALUE : NULL;
 
   /* Setup our write end of the process pipe.  Clear the one in the structure.
      The destructor should never be called for this but, it can't hurt to be
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 445bd35..064299e 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -35,7 +35,7 @@ public:
 
 pinfo_basic::pinfo_basic ()
 {
-  pid = dwProcessId = GetCurrentProcessId ();
+  dwProcessId = GetCurrentProcessId ();
   PWCHAR pend = wcpncpy (progname, global_progname,
 			 sizeof (progname) / sizeof (WCHAR) - 1);
   *pend = L'\0';
@@ -57,15 +57,20 @@ pinfo::thisproc (HANDLE h)
   procinfo = NULL;
 
   DWORD flags = PID_IN_USE | PID_ACTIVE;
+  /* Forked process or process started from non-Cygwin parent needs a pid. */
   if (!h)
     {
       cygheap->pid = create_cygwin_pid ();
       flags |= PID_NEW;
     }
+  /* spawnve'd process got pid in parent, cygheap->pid has been set in
+     child_info_spawn::handle_spawn. */
+  else if (h == INVALID_HANDLE_VALUE)
+    h = NULL;
 
   init (cygheap->pid, flags, h);
   procinfo->process_state |= PID_IN_USE;
-  procinfo->dwProcessId = myself_initial.pid;
+  procinfo->dwProcessId = myself_initial.dwProcessId;
   procinfo->sendsig = myself_initial.sendsig;
   wcscpy (procinfo->progname, myself_initial.progname);
   create_winpid_symlink ();
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index d969c66..ebc34d1 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -258,7 +258,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 			  int in__stdin, int in__stdout)
 {
   bool rc;
-  pid_t cygpid;
   int res = -1;
 
   /* Check if we have been called from exec{lv}p or spawn{lv}p and mask
@@ -578,6 +577,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
       if (!real_path.iscygexec () && mode == _P_OVERLAY)
 	myself->process_state |= PID_NOTCYGWIN;
 
+      cygpid = (mode != _P_OVERLAY) ? create_cygwin_pid () : myself->pid;
+
       wchar_t wcmd[(size_t) cmd];
       if (!::cygheap->user.issetuid ()
 	  || (::cygheap->user.saved_uid == ::cygheap->user.real_uid
@@ -708,11 +709,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
       if (::cygheap->fdtab.need_fixup_before ())
 	::cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
 
-      if (mode != _P_OVERLAY)
-	cygpid = create_cygwin_pid ();
-      else
-	cygpid = myself->pid;
-
       /* Print the original program name here so the user can see that too.  */
       syscall_printf ("pid %d, prog_arg %s, cmd line %.9500s)",
 		      rc ? cygpid : (unsigned int) -1, prog_arg, (const char *) cmd);



More information about the Cygwin-cvs mailing list