* child_info.h (child_info_fork::parent_wr_proc_pipe): New element.

* fork.cc (fork_parent): Set parent_wr_proc.
* pinfo.cc (set_myself): Close child_proc_info->parent_wr_proc if it exists
rather than trying to get value from parent _pinfo.
* pinfo.h (enum parent_aleter): New enum.
(pinfo::alert_parent): Declare as returning a value.
(pinfo::parent_alive): New function.
* pinfo.cc (pinfo::alert_parent): Set wr_proc_pipe to invalid non-NULL value
when parent disappears.  Return success of operation.
(proc_waiter): Use __ALERT_* enum for control since these are not really
signals.  Implement __ALERT_ALIVE.
* sigproc.cc (my_parent_is_alive): Eliminate.
* sigproc.h (my_parent_is_alive): Ditto for declaration.
(__SIGREPARENT): Eliminate.
This commit is contained in:
Christopher Faylor 2004-12-03 04:46:00 +00:00
parent 3ef7d75861
commit 82b7b4fd4f
8 changed files with 69 additions and 48 deletions

View File

@ -1,3 +1,23 @@
2004-12-02 Christopher Faylor <cgf@timesys.com>
* child_info.h (child_info_fork::parent_wr_proc_pipe): New element.
* fork.cc (fork_parent): Set parent_wr_proc.
* pinfo.cc (set_myself): Close child_proc_info->parent_wr_proc if it
exists rather than trying to get value from parent _pinfo.
2004-12-02 Christopher Faylor <cgf@timesys.com>
* pinfo.h (enum parent_aleter): New enum.
(pinfo::alert_parent): Declare as returning a value.
(pinfo::parent_alive): New function.
* pinfo.cc (pinfo::alert_parent): Set wr_proc_pipe to invalid non-NULL
value when parent disappears. Return success of operation.
(proc_waiter): Use __ALERT_* enum for control since these are not really signals.
Implement __ALERT_ALIVE.
* sigproc.cc (my_parent_is_alive): Eliminate.
* sigproc.h (my_parent_is_alive): Ditto for declaration.
(__SIGREPARENT): Eliminate.
2004-12-02 Christopher Faylor <cgf@timesys.com>
* pinfo.cc (pinfo::wait): Use better name for cygthread.

View File

@ -29,7 +29,7 @@ enum
#define EXEC_MAGIC_SIZE sizeof(child_info)
#define CURR_CHILD_INFO_MAGIC 0x83e9a7b7U
#define CURR_CHILD_INFO_MAGIC 0x694cd4b8U
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@ -49,6 +49,7 @@ public:
void *cygheap_max;
DWORD cygheap_reserve_sz;
HANDLE cygheap_h;
HANDLE parent_wr_proc_pipe;
unsigned fhandler_union_cb;
};

View File

@ -401,6 +401,8 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
init_child_info (PROC_FORK, &ch, subproc_ready);
ch.forker_finished = forker_finished;
ch.parent_wr_proc_pipe = myself->wr_proc_pipe == INVALID_HANDLE_VALUE
? NULL : myself->wr_proc_pipe;
stack_base (ch);

View File

@ -32,6 +32,7 @@ details. */
#include "fhandler.h"
#include "cygmalloc.h"
#include "cygtls.h"
#include "child_info.h"
static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0};
@ -43,6 +44,8 @@ pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks
void __stdcall
set_myself (HANDLE h)
{
extern child_info *child_proc_info;
if (!h)
cygheap->pid = cygwin_pid (GetCurrentProcessId ());
myself.init (cygheap->pid, PID_IN_USE | PID_MYSELF, h);
@ -61,22 +64,19 @@ set_myself (HANDLE h)
static pinfo NO_COPY myself_identity;
myself_identity.init (cygwin_pid (myself->dwProcessId), PID_EXECED);
}
else if (myself->ppid)
else if (myself->wr_proc_pipe)
{
/* here if forked/spawned */
pinfo parent (myself->ppid);
/* We've inherited the parent's wr_proc_pipe. We don't need it,
so close it. This could cause problems for the spawn case since there
is no guarantee that a parent will still be around by the time we get
here. If so, we would have a handle leak. FIXME? */
if (parent && parent->wr_proc_pipe)
CloseHandle (parent->wr_proc_pipe);
so close it. */
if (child_proc_info->parent_wr_proc_pipe)
CloseHandle (child_proc_info->parent_wr_proc_pipe);
if (cygheap->pid_handle)
{
ForceCloseHandle (cygheap->pid_handle);
cygheap->pid_handle = NULL;
}
}
# undef child_proc_info
return;
}
@ -704,6 +704,8 @@ proc_waiter (void *arg)
switch (buf)
{
case __ALERT_ALIVE:
continue;
case 0:
/* Child exited. Do some cleanup and signal myself. */
CloseHandle (vchild.rd_proc_pipe);
@ -733,7 +735,7 @@ proc_waiter (void *arg)
break;
case SIGCONT:
continue;
case __SIGREPARENT: /* sigh */
case __ALERT_REPARENT: /* sigh */
/* spawn_guts has signalled us that it has just started a new
subprocess which will take over this cygwin pid. */
@ -830,23 +832,26 @@ pinfo::wait ()
/* function to send a "signal" to the parent when something interesting happens
in the child. */
void
bool
pinfo::alert_parent (char sig)
{
DWORD nb;
DWORD nb = 0;
/* Send something to our parent. If the parent has gone away,
close the pipe. */
if (myself->wr_proc_pipe
&& WriteFile (myself->wr_proc_pipe, &sig, 1, &nb, NULL))
if (myself->wr_proc_pipe == INVALID_HANDLE_VALUE)
/* no parent */;
else if (myself->wr_proc_pipe
&& WriteFile (myself->wr_proc_pipe, &sig, 1, &nb, NULL))
/* all is well */;
else if (GetLastError () != ERROR_BROKEN_PIPE)
debug_printf ("sending %d notification to parent failed, %E", sig);
else
{
HANDLE closeit = myself->wr_proc_pipe;
myself->wr_proc_pipe = NULL;
myself->wr_proc_pipe = INVALID_HANDLE_VALUE;
CloseHandle (closeit);
}
return (bool) nb;
}
void

View File

@ -118,6 +118,12 @@ public:
friend class pinfo;
};
enum parent_alerter
{
__ALERT_REPARENT = 111, // arbitrary non-signal value
__ALERT_ALIVE = 112
};
class pinfo
{
HANDLE h;
@ -153,7 +159,8 @@ public:
operator _pinfo * () const {return procinfo;}
// operator bool () const {return (int) h;}
void preserve () { destroy = false; }
void alert_parent (char);
bool alert_parent (char);
bool parent_alive () { return alert_parent (__ALERT_ALIVE); }
#ifndef _SIGPROC_H
int remember () {system_printf ("remember is not here"); return 0;}
#else

View File

@ -125,23 +125,6 @@ signal_fixup_after_exec ()
}
}
/* Determine if the parent process is alive.
*/
bool __stdcall
my_parent_is_alive ()
{
bool res;
if (myself->cygstarted)
res = pid_exists (myself->ppid);
else
{
debug_printf ("Not started by cygwin app");
res = false;
}
return res;
}
void __stdcall
wait_for_sigthread ()
{

View File

@ -22,8 +22,7 @@ enum
__SIGDELETE = -(NSIG + 5),
__SIGFLUSHFAST = -(NSIG + 6),
__SIGHOLD = -(NSIG + 7),
__SIGNOHOLD = -(NSIG + 8),
__SIGREPARENT = (NSIG + 2)
__SIGNOHOLD = -(NSIG + 8)
};
#endif
@ -55,7 +54,6 @@ struct sigpacket
extern HANDLE signal_arrived;
extern HANDLE sigCONT;
bool __stdcall my_parent_is_alive ();
void __stdcall sig_dispatch_pending (bool fast = false);
#ifdef _PINFO_H
extern "C" void __stdcall set_signal_mask (sigset_t newmask, sigset_t = myself->getsigmask ());

View File

@ -636,6 +636,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
ProtectHandle (cygheap->pid_handle);
else
system_printf ("duplicate to pid_handle failed, %E");
ciresrv.parent_wr_proc_pipe = myself->wr_proc_pipe;
}
/* Start the process in a suspended state. Needed so that any potential parent will
@ -643,7 +644,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
to handle exec'ed windows processes since cygwin processes are smart enough that
the parent doesn't have to bother but what are you gonna do? Cygwin lives in
a windows world. */
flags |= CREATE_SUSPENDED;
if (mode != _P_OVERLAY || !real_path.iscygexec ())
flags |= CREATE_SUSPENDED;
const char *runpath = null_app_name ? NULL : (const char *) real_path;
@ -784,21 +786,24 @@ spawn_guts (const char * prog_arg, const char *const *argv,
DWORD exec_cygstarted;
if (mode == _P_OVERLAY)
{
/* Store the old exec_cygstarted since this is used as a crude semaphore for
detecting when the parent has noticed the change in windows pid for this
cygwin pid. */
exec_cygstarted = myself->cygstarted;
myself->dwProcessId = dwExeced = pi.dwProcessId; /* Reparenting needs this */
myself.alert_parent (__SIGREPARENT);
if (!real_path.iscygexec ())
{
/* Store the old exec_cygstarted since this is used as a crude semaphore for
detecting when the parent has noticed the change in windows pid for this
cygwin pid. */
exec_cygstarted = myself->cygstarted;
myself->dwProcessId = dwExeced = pi.dwProcessId; /* Reparenting needs this */
myself.alert_parent (__ALERT_REPARENT);
}
CloseHandle (saved_sendsig);
strace.execing = 1;
hExeced = pi.hProcess;
strcpy (myself->progname, real_path);
strcpy (myself->progname, real_path); // FIXME: race?
close_all_files ();
/* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
/* If wr_proc_pipe is NULL then this process was not started by a cygwin
process. So, we need to wait around until the process we've just "execed"
dies. Use our own wait facility to wait for our own pid to exit (there
is some minor special case code in proc_waiter and friends to accommodeate
is some minor special case code in proc_waiter and friends to accommodate
this). */
if (!myself->wr_proc_pipe)
{
@ -854,9 +859,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
else
{
/* Loop, waiting for parent to notice pid change, if exec_cygstarted.
In theory this wait should be a no-op. */
In theory this wait should usually be a no-op. */
if (exec_cygstarted)
while (myself->cygstarted == exec_cygstarted)
while (myself->cygstarted == exec_cygstarted && myself.parent_alive ())
low_priority_sleep (0);
res = 42;
}