4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-21 16:26:12 +08:00

* 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.
This commit is contained in:
Christopher Faylor 2011-10-26 19:42:39 +00:00
parent be2280986d
commit b79b15e9e3
9 changed files with 129 additions and 27 deletions

View 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> 2011-10-25 Corinna Vinschen <corinna@vinschen.de>
* hookapi.cc (hook_or_detect_cygwin): Take additional handle * hookapi.cc (hook_or_detect_cygwin): Take additional handle

View File

@ -38,10 +38,16 @@ enum child_status
#define EXEC_MAGIC_SIZE sizeof(child_info) #define EXEC_MAGIC_SIZE sizeof(child_info)
/* Change this value if you get a message indicating that it is out-of-sync. */ /* 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 #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 /* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between below class. The layout is checksummed to determine compatibility between
different cygwin versions. */ different cygwin versions. */
@ -56,8 +62,6 @@ public:
HANDLE subproc_ready; // used for synchronization with parent HANDLE subproc_ready; // used for synchronization with parent
HANDLE user_h; HANDLE user_h;
HANDLE parent; HANDLE parent;
int nprocs;
pid_t children[NPROCS];
init_cygheap *cygheap; init_cygheap *cygheap;
void *cygheap_max; void *cygheap_max;
DWORD cygheap_reserve_sz; DWORD cygheap_reserve_sz;
@ -119,6 +123,8 @@ public:
int __stdin; int __stdin;
int __stdout; int __stdout;
char filler[4]; char filler[4];
int nchildren;
cchildren children[NPROCS];
~child_info_spawn () ~child_info_spawn ()
{ {
@ -135,8 +141,10 @@ public:
cfree (moreinfo); cfree (moreinfo);
} }
} }
child_info_spawn (): moreinfo (NULL) {}; child_info_spawn (): moreinfo (NULL), nchildren (0) {};
child_info_spawn (child_info_types, bool); 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 *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 set (child_info_types ci, bool b) { new (this) child_info_spawn (ci, b);}
void handle_spawn () __attribute__ ((regparm (1))); void handle_spawn () __attribute__ ((regparm (1)));

View File

@ -625,6 +625,12 @@ child_info_spawn::handle_spawn ()
cygheap->fdtab.move_fd (__stdout, 1); cygheap->fdtab.move_fd (__stdout, 1);
cygheap->user.groups.clear_supp (); 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); ready (true);
/* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of

View File

@ -22,7 +22,7 @@ HANDLE NO_COPY hMainThread;
HANDLE NO_COPY hProcToken; HANDLE NO_COPY hProcToken;
HANDLE NO_COPY hProcImpToken; HANDLE NO_COPY hProcImpToken;
HMODULE NO_COPY cygwin_hmodule; HMODULE NO_COPY cygwin_hmodule;
HANDLE hExeced; HANDLE NO_COPY hExeced;
int NO_COPY sigExeced; int NO_COPY sigExeced;
WCHAR NO_COPY windows_system_directory[MAX_PATH]; WCHAR NO_COPY windows_system_directory[MAX_PATH];
UINT NO_COPY windows_system_directory_length; UINT NO_COPY windows_system_directory_length;

View File

@ -971,19 +971,25 @@ _pinfo::dup_proc_pipe (HANDLE hProcess)
int int
pinfo::wait () pinfo::wait ()
{ {
/* FIXME: execed processes should be able to wait for pids that were started /* If rd_proc_pipe that means we're in an execed process which already has
by the process which execed them. */ grabbed the read end of the pipe from the previous cygwin process running
if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16)) with this pid. */
if (!rd_proc_pipe)
{ {
system_printf ("Couldn't create pipe tracker for pid %d, %E", /* FIXME: execed processes should be able to wait for pids that were started
(*this)->pid); by the process which execed them. */
return 0; 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)) if (!(*this)->dup_proc_pipe (hProcess))
{ {
system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess); system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
return 0; return 0;
}
} }
preserve (); /* Preserve the shared memory associated with the pinfo */ preserve (); /* Preserve the shared memory associated with the pinfo */

View File

@ -147,8 +147,8 @@ public:
bool waiter_ready; bool waiter_ready;
class cygthread *wait_thread; class cygthread *wait_thread;
void init (pid_t, DWORD, HANDLE) __attribute__ ((regparm(3))); void init (pid_t, DWORD, HANDLE) __attribute__ ((regparm(3)));
pinfo (): procinfo (NULL) {} pinfo (): procinfo (NULL), rd_proc_pipe (NULL) {}
pinfo (_pinfo *x): procinfo (x), hProcess (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) : 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);} 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))); void thisproc (HANDLE) __attribute__ ((regparm (2)));
@ -175,6 +175,11 @@ public:
#ifndef _SIGPROC_H #ifndef _SIGPROC_H
int remember () {system_printf ("remember is not here"); return 0;} int remember () {system_printf ("remember is not here"); return 0;}
#else #else
void reattach ()
{
proc_subproc (PROC_REATTACH_CHILD, (DWORD) this);
destroy = false;
}
int remember (bool detach) int remember (bool detach)
{ {
int res = proc_subproc (detach ? PROC_DETACHED_CHILD : PROC_ADDCHILD, int res = proc_subproc (detach ? PROC_DETACHED_CHILD : PROC_ADDCHILD,

View File

@ -14,7 +14,6 @@ details. */
#include <stdlib.h> #include <stdlib.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "pinfo.h"
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
@ -23,6 +22,7 @@ details. */
#include "shared_info.h" #include "shared_info.h"
#include "cygtls.h" #include "cygtls.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h"
#include "ntdll.h" #include "ntdll.h"
/* /*
@ -129,6 +129,8 @@ signal_fixup_after_exec ()
static bool static bool
get_proc_lock (DWORD what, DWORD val) get_proc_lock (DWORD what, DWORD val)
{ {
if (!cygwin_finished_initializing)
return true;
Static int lastwhat = -1; Static int lastwhat = -1;
if (!sync_proc_subproc) if (!sync_proc_subproc)
{ {
@ -234,6 +236,9 @@ proc_subproc (DWORD what, DWORD val)
} }
if (what == PROC_DETACHED_CHILD) if (what == PROC_DETACHED_CHILD)
break; break;
/* fall through intentionally */
case PROC_REATTACH_CHILD:
procs[nprocs] = vchild; procs[nprocs] = vchild;
rc = procs[nprocs].wait (); rc = procs[nprocs].wait ();
if (rc) if (rc)
@ -379,6 +384,7 @@ proc_terminate ()
set to 1 so we don't do that either. set to 1 so we don't do that either.
if (!hExeced) if (!hExeced)
*/ */
if (!hExeced || ISSTATE (myself, PID_NOTCYGWIN))
procs[i]->ppid = 1; procs[i]->ppid = 1;
if (procs[i].wait_thread) if (procs[i].wait_thread)
{ {
@ -596,8 +602,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
goto out; goto out;
} }
VerifyHandle (hp); VerifyHandle (hp);
if (!DuplicateHandle (hp, dupsig, GetCurrentProcess (), &sendsig, false, if (!DuplicateHandle (hp, dupsig, GetCurrentProcess (), &sendsig, 0,
0, DUPLICATE_SAME_ACCESS) || !sendsig) false, DUPLICATE_SAME_ACCESS) || !sendsig)
{ {
__seterrno (); __seterrno ();
sigproc_printf ("DuplicateHandle failed, %E"); sigproc_printf ("DuplicateHandle failed, %E");
@ -619,7 +625,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
__seterrno (); __seterrno ();
goto out; goto out;
} }
if (!DuplicateHandle (GetCurrentProcess (), tome, hp, &tome, false, 0, if (!DuplicateHandle (GetCurrentProcess (), tome, hp, &tome, 0, false,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
{ {
sigproc_printf ("DuplicateHandle for __SIGCOMMUNE failed, %E"); 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. */ allow the child to duplicate handles from the parent to itself. */
parent = NULL; parent = NULL;
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (), if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
GetCurrentProcess (), &parent, 0, TRUE, GetCurrentProcess (), &parent, 0, true,
DUPLICATE_SAME_ACCESS)) DUPLICATE_SAME_ACCESS))
system_printf ("couldn't create handle to myself for child, %E"); 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 void
child_info::ready (bool execed) child_info::ready (bool execed)
{ {

View File

@ -34,10 +34,11 @@ enum
enum procstuff enum procstuff
{ {
PROC_ADDCHILD = 1, // add a new subprocess to list PROC_ADDCHILD = 1, // add a new subprocess to list
PROC_DETACHED_CHILD = 2, // set up a detached child PROC_REATTACH_CHILD = 2, // reattach after exec
PROC_CLEARWAIT = 3, // clear all waits - signal arrived PROC_DETACHED_CHILD = 3, // set up a detached child
PROC_WAIT = 4, // setup for wait() for subproc PROC_CLEARWAIT = 4, // clear all waits - signal arrived
PROC_NOTHING = 5 // nothing, really PROC_WAIT = 5, // setup for wait() for subproc
PROC_NOTHING = 6 // nothing, really
}; };
struct sigpacket struct sigpacket

View File

@ -546,6 +546,8 @@ spawn_guts (const char *prog_arg, const char *const *argv,
ch.moreinfo = moreinfo; ch.moreinfo = moreinfo;
ch.__stdin = __stdin; ch.__stdin = __stdin;
ch.__stdout = __stdout; ch.__stdout = __stdout;
if (mode == _P_OVERLAY && ch.iscygwin ())
ch.record_children ();
si.lpReserved2 = (LPBYTE) &ch; si.lpReserved2 = (LPBYTE) &ch;
si.cbReserved2 = sizeof (ch); si.cbReserved2 = sizeof (ch);