Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2011-10-26 23:42:39 +0400
committerChristopher Faylor <me@cgf.cx>2011-10-26 23:42:39 +0400
commitb79b15e9e3160ef31b8ace8f167a8e9647670647 (patch)
treed688fb10d662cdb5248c4c1c6966db9218084186 /winsup
parentbe2280986de5339bca3d648ec0e7538541dcd674 (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog32
-rw-r--r--winsup/cygwin/child_info.h16
-rw-r--r--winsup/cygwin/dcrt0.cc6
-rw-r--r--winsup/cygwin/globals.cc2
-rw-r--r--winsup/cygwin/pinfo.cc28
-rw-r--r--winsup/cygwin/pinfo.h9
-rw-r--r--winsup/cygwin/sigproc.cc52
-rw-r--r--winsup/cygwin/sigproc.h9
-rw-r--r--winsup/cygwin/spawn.cc2
9 files changed, 129 insertions, 27 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 2e2c194d0..bf71c0d25 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index ef7166f2d..95cb4d6eb 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -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)));
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index dd3ff021c..7c85f315a 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -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
diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc
index ae8cb5266..0b2ed573c 100644
--- a/winsup/cygwin/globals.cc
+++ b/winsup/cygwin/globals.cc
@@ -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;
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 842b4275f..5a77d8f6c 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -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 */
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 746f99350..f9e859cde 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -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,
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 00a2c8af9..fc5f816f4 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -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)
{
diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h
index e0ea5e433..b63e5731a 100644
--- a/winsup/cygwin/sigproc.h
+++ b/winsup/cygwin/sigproc.h
@@ -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
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index f9e1504b1..490efd73c 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -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);