OSDN Git Service

* child_info.h (cchildren): New struct.
authorcgf <cgf>
Wed, 26 Oct 2011 19:42:37 +0000 (19:42 +0000)
committercgf <cgf>
Wed, 26 Oct 2011 19:42:37 +0000 (19:42 +0000)
(child_info_spawn::nchildren): Rename from nprocs.
(child_info_spawn::children): Change type to cchildren for more bookkeeping
possibilities.
(child_info_spawn::child_info_spawn): Clear nchildren.
(child_info_spawn::record_children): Declare new function.
(child_info_spawn::reattach_children): Ditto.
* dcrt0.cc (child_info_spawn::handle_spawn): Call reattach_children to gather
list of processes we are potentially waiting for.
* pinfo.h (pinfo::pinfo): Make sure that rd_proc_pipe is always cleared.
(pinfo::reattach): New function.
* sigproc.cc: Move pinfo.h earlier so that it can be used in sigproc.h.
(get_proc_lock): Don't bother with a lock during DLL initialization.
(proc_subproc): Handle PROC_REATTACH_CHILD.
(proc_terminate): Orphan children only when we are not an execed process or
when the pid is about to be occupied by a non-cygwin process.
(child_info_spawn::record_children): Define new function.
(child_info_spawn::reattach_children): Ditto.
* sigproc.h (procstuff): Define PROC_REATTACH_CHILD and renumber other
elements.
* spawn.cc (spawn_guts): Record any to-be-waited-for subprocesses if about to
exec a cygwin process.
* sigproc.cc (sig_send): Fix harmless transposition of fifth and six arguments
to DuplicateHandle().
(child_info::child_info): Ditto.
* globals.cc (hExeced): Make NO_COPY.

winsup/cygwin/ChangeLog
winsup/cygwin/child_info.h
winsup/cygwin/dcrt0.cc
winsup/cygwin/globals.cc
winsup/cygwin/pinfo.cc
winsup/cygwin/pinfo.h
winsup/cygwin/sigproc.cc
winsup/cygwin/sigproc.h
winsup/cygwin/spawn.cc

index 2e2c194..bf71c0d 100644 (file)
@@ -1,3 +1,35 @@
+2011-10-25  Christopher Faylor  <me.cygwin2011@cgf.cx>
+
+       * child_info.h (cchildren): New struct.
+       (child_info_spawn::nchildren): Rename from nprocs.
+       (child_info_spawn::children): Change type to cchildren for more
+       bookkeeping possibilities.
+       (child_info_spawn::child_info_spawn): Clear nchildren.
+       (child_info_spawn::record_children): Declare new function.
+       (child_info_spawn::reattach_children): Ditto.
+       * dcrt0.cc (child_info_spawn::handle_spawn): Call reattach_children to
+       gather list of processes we are potentially waiting for.
+       * pinfo.h (pinfo::pinfo): Make sure that rd_proc_pipe is always cleared.
+       (pinfo::reattach): New function.
+       * sigproc.cc: Move pinfo.h earlier so that it can be used in sigproc.h.
+       (get_proc_lock): Don't bother with a lock during DLL initialization.
+       (proc_subproc): Handle PROC_REATTACH_CHILD.
+       (proc_terminate): Orphan children only when we are not an execed
+       process or when the pid is about to be occupied by a non-cygwin
+       process.
+       (child_info_spawn::record_children): Define new function.
+       (child_info_spawn::reattach_children): Ditto.
+       * sigproc.h (procstuff): Define PROC_REATTACH_CHILD and renumber other
+       elements.
+       * spawn.cc (spawn_guts): Record any to-be-waited-for subprocesses if
+       about to exec a cygwin process.
+
+       * sigproc.cc (sig_send): Fix harmless transposition of fifth and six
+       arguments to DuplicateHandle().
+       (child_info::child_info): Ditto.
+
+       * globals.cc (hExeced): Make NO_COPY.
+
 2011-10-25  Corinna Vinschen  <corinna@vinschen.de>
 
        * hookapi.cc (hook_or_detect_cygwin): Take additional handle
index ef7166f..95cb4d6 100644 (file)
@@ -38,10 +38,16 @@ 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 0x29afd207U
+#define CURR_CHILD_INFO_MAGIC 0xa049a83aU
 
 #define NPROCS 256
 
+struct cchildren
+{
+  pid_t pid;
+  HANDLE rd_proc_pipe;
+};
+
 /* NOTE: Do not make gratuitous changes to the names or organization of the
    below class.  The layout is checksummed to determine compatibility between
    different cygwin versions. */
@@ -56,8 +62,6 @@ public:
   HANDLE subproc_ready;        // used for synchronization with parent
   HANDLE user_h;
   HANDLE parent;
-  int nprocs;
-  pid_t children[NPROCS];
   init_cygheap *cygheap;
   void *cygheap_max;
   DWORD cygheap_reserve_sz;
@@ -119,6 +123,8 @@ public:
   int __stdin;
   int __stdout;
   char filler[4];
+  int nchildren;
+  cchildren children[NPROCS];
 
   ~child_info_spawn ()
   {
@@ -135,8 +141,10 @@ public:
        cfree (moreinfo);
       }
   }
-  child_info_spawn (): moreinfo (NULL) {};
+  child_info_spawn (): moreinfo (NULL), nchildren (0) {};
   child_info_spawn (child_info_types, bool);
+  void record_children ();
+  void reattach_children ();
   void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;}
   void set (child_info_types ci, bool b) { new (this) child_info_spawn (ci, b);}
   void handle_spawn () __attribute__ ((regparm (1)));
index dd3ff02..7c85f31 100644 (file)
@@ -625,6 +625,12 @@ child_info_spawn::handle_spawn ()
     cygheap->fdtab.move_fd (__stdout, 1);
   cygheap->user.groups.clear_supp ();
 
+  /* If we're execing we may have "inherited" a list of children forked by the
+     previous process executing under this pid.  Reattach them here so that we
+     can wait for them.  */
+  if (type == _PROC_EXEC)
+    reattach_children ();
+
   ready (true);
 
   /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
index ae8cb52..0b2ed57 100644 (file)
@@ -22,7 +22,7 @@ HANDLE NO_COPY hMainThread;
 HANDLE NO_COPY hProcToken;
 HANDLE NO_COPY hProcImpToken;
 HMODULE NO_COPY cygwin_hmodule;
-HANDLE hExeced;
+HANDLE NO_COPY hExeced;
 int NO_COPY sigExeced;
 WCHAR NO_COPY windows_system_directory[MAX_PATH];
 UINT NO_COPY windows_system_directory_length;
index 842b427..5a77d8f 100644 (file)
@@ -971,19 +971,25 @@ _pinfo::dup_proc_pipe (HANDLE hProcess)
 int
 pinfo::wait ()
 {
-  /* FIXME: execed processes should be able to wait for pids that were started
-     by the process which execed them. */
-  if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16))
+  /* If rd_proc_pipe that means we're in an execed process which already has
+     grabbed the read end of the pipe from the previous cygwin process running
+     with this pid.  */
+  if (!rd_proc_pipe)
     {
-      system_printf ("Couldn't create pipe tracker for pid %d, %E",
-                    (*this)->pid);
-      return 0;
-    }
+      /* FIXME: execed processes should be able to wait for pids that were started
+        by the process which execed them. */
+      if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16))
+       {
+         system_printf ("Couldn't create pipe tracker for pid %d, %E",
+                        (*this)->pid);
+         return 0;
+       }
 
-  if (!(*this)->dup_proc_pipe (hProcess))
-    {
-      system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
-      return 0;
+      if (!(*this)->dup_proc_pipe (hProcess))
+       {
+         system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
+         return 0;
+       }
     }
 
   preserve ();         /* Preserve the shared memory associated with the pinfo */
index 746f993..f9e859c 100644 (file)
@@ -147,8 +147,8 @@ public:
   bool waiter_ready;
   class cygthread *wait_thread;
   void init (pid_t, DWORD, HANDLE) __attribute__ ((regparm(3)));
-  pinfo (): procinfo (NULL) {}
-  pinfo (_pinfo *x): procinfo (x), hProcess (NULL) {}
+  pinfo (): procinfo (NULL), rd_proc_pipe (NULL) {}
+  pinfo (_pinfo *x): procinfo (x), rd_proc_pipe (NULL), hProcess (NULL) {}
   pinfo (pid_t n) : rd_proc_pipe (NULL), hProcess (NULL) {init (n, 0, NULL);}
   pinfo (pid_t n, DWORD flag) : rd_proc_pipe (NULL), hProcess (NULL), waiter_ready (0), wait_thread (NULL) {init (n, flag, NULL);}
   void thisproc (HANDLE) __attribute__ ((regparm (2)));
@@ -175,6 +175,11 @@ public:
 #ifndef _SIGPROC_H
   int remember () {system_printf ("remember is not here"); return 0;}
 #else
+  void reattach ()
+  {
+    proc_subproc (PROC_REATTACH_CHILD, (DWORD) this);
+    destroy = false;
+  }
   int remember (bool detach)
   {
     int res = proc_subproc (detach ? PROC_DETACHED_CHILD : PROC_ADDCHILD,
index 00a2c8a..fc5f816 100644 (file)
@@ -14,7 +14,6 @@ details. */
 #include <stdlib.h>
 #include <sys/cygwin.h>
 #include "cygerrno.h"
-#include "pinfo.h"
 #include "path.h"
 #include "fhandler.h"
 #include "dtable.h"
@@ -23,6 +22,7 @@ details. */
 #include "shared_info.h"
 #include "cygtls.h"
 #include "sigproc.h"
+#include "pinfo.h"
 #include "ntdll.h"
 
 /*
@@ -129,6 +129,8 @@ signal_fixup_after_exec ()
 static bool
 get_proc_lock (DWORD what, DWORD val)
 {
+  if (!cygwin_finished_initializing)
+    return true;
   Static int lastwhat = -1;
   if (!sync_proc_subproc)
     {
@@ -234,6 +236,9 @@ proc_subproc (DWORD what, DWORD val)
        }
       if (what == PROC_DETACHED_CHILD)
        break;
+      /* fall through intentionally */
+
+    case PROC_REATTACH_CHILD:
       procs[nprocs] = vchild;
       rc = procs[nprocs].wait ();
       if (rc)
@@ -379,6 +384,7 @@ proc_terminate ()
             set to 1 so we don't do that either.
          if (!hExeced)
             */
+         if (!hExeced || ISSTATE (myself, PID_NOTCYGWIN))
            procs[i]->ppid = 1;
          if (procs[i].wait_thread)
            {
@@ -596,8 +602,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
          goto out;
        }
       VerifyHandle (hp);
-      if (!DuplicateHandle (hp, dupsig, GetCurrentProcess (), &sendsig, false,
-                           0, DUPLICATE_SAME_ACCESS) || !sendsig)
+      if (!DuplicateHandle (hp, dupsig, GetCurrentProcess (), &sendsig, 0,
+                           false, DUPLICATE_SAME_ACCESS) || !sendsig)
        {
          __seterrno ();
          sigproc_printf ("DuplicateHandle failed, %E");
@@ -619,7 +625,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
              __seterrno ();
              goto out;
            }
-         if (!DuplicateHandle (GetCurrentProcess (), tome, hp, &tome, false, 0,
+         if (!DuplicateHandle (GetCurrentProcess (), tome, hp, &tome, 0, false,
                                DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
            {
              sigproc_printf ("DuplicateHandle for __SIGCOMMUNE failed, %E");
@@ -807,7 +813,7 @@ child_info::child_info (unsigned in_cb, child_info_types chtype, bool need_subpr
      allow the child to duplicate handles from the parent to itself. */
   parent = NULL;
   if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
-                       GetCurrentProcess (), &parent, 0, TRUE,
+                       GetCurrentProcess (), &parent, 0, true,
                        DUPLICATE_SAME_ACCESS))
     system_printf ("couldn't create handle to myself for child, %E");
 }
@@ -830,6 +836,42 @@ child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_r
 {
 }
 
+/* Record any non-reaped subprocesses to be passed to about-to-be-execed
+   process.  FIXME: There is a race here if the process exits while we
+   are recording it.  */
+void
+child_info_spawn::record_children ()
+{
+  /* FIXME: locking */
+  for (nchildren = 0; nchildren < nprocs; nchildren++)
+    {
+      children[nchildren].pid = procs[nchildren]->pid;
+      children[nchildren].rd_proc_pipe = procs[nchildren].rd_proc_pipe;
+    }
+}
+
+/* Reattach non-reaped subprocesses passed in from the cygwin process
+   which previously operated under this pid.  FIXME: Is there a race here
+   if the process exits during cygwin's exec handoff?  */
+void
+child_info_spawn::reattach_children ()
+{
+  for (int i = 0; i < nchildren; i++)
+    {
+      pinfo p (children[i].pid, PID_MAP_RW);
+      if (p)
+       {
+         if (!DuplicateHandle (parent, children[i].rd_proc_pipe,
+                               GetCurrentProcess (), &p.rd_proc_pipe, 0,
+                               false, DUPLICATE_SAME_ACCESS))
+           system_printf ("couldn't duplicate parent %p handles for forked children after exec, %E",
+                          children[i].rd_proc_pipe);
+         p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, p->pid);
+         p.reattach ();
+       }
+    }
+}
+
 void
 child_info::ready (bool execed)
 {
index e0ea5e4..b63e573 100644 (file)
@@ -34,10 +34,11 @@ enum
 enum procstuff
 {
   PROC_ADDCHILD                  = 1,  // add a new subprocess to list
-  PROC_DETACHED_CHILD    = 2,  // set up a detached child
-  PROC_CLEARWAIT         = 3,  // clear all waits - signal arrived
-  PROC_WAIT              = 4,  // setup for wait() for subproc
-  PROC_NOTHING           = 5   // nothing, really
+  PROC_REATTACH_CHILD    = 2,  // reattach after exec
+  PROC_DETACHED_CHILD    = 3,  // set up a detached child
+  PROC_CLEARWAIT         = 4,  // clear all waits - signal arrived
+  PROC_WAIT              = 5,  // setup for wait() for subproc
+  PROC_NOTHING           = 6   // nothing, really
 };
 
 struct sigpacket
index f9e1504..490efd7 100644 (file)
@@ -546,6 +546,8 @@ spawn_guts (const char *prog_arg, const char *const *argv,
   ch.moreinfo = moreinfo;
   ch.__stdin = __stdin;
   ch.__stdout = __stdout;
+  if (mode == _P_OVERLAY && ch.iscygwin ())
+    ch.record_children ();
 
   si.lpReserved2 = (LPBYTE) &ch;
   si.cbReserved2 = sizeof (ch);