* 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> 2004-12-02 Christopher Faylor <cgf@timesys.com>
* pinfo.cc (pinfo::wait): Use better name for cygthread. * pinfo.cc (pinfo::wait): Use better name for cygthread.

View File

@ -29,7 +29,7 @@ enum
#define EXEC_MAGIC_SIZE sizeof(child_info) #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 /* 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
@ -49,6 +49,7 @@ public:
void *cygheap_max; void *cygheap_max;
DWORD cygheap_reserve_sz; DWORD cygheap_reserve_sz;
HANDLE cygheap_h; HANDLE cygheap_h;
HANDLE parent_wr_proc_pipe;
unsigned fhandler_union_cb; 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); init_child_info (PROC_FORK, &ch, subproc_ready);
ch.forker_finished = forker_finished; 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); stack_base (ch);

View File

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

View File

@ -118,6 +118,12 @@ public:
friend class pinfo; friend class pinfo;
}; };
enum parent_alerter
{
__ALERT_REPARENT = 111, // arbitrary non-signal value
__ALERT_ALIVE = 112
};
class pinfo class pinfo
{ {
HANDLE h; HANDLE h;
@ -153,7 +159,8 @@ public:
operator _pinfo * () const {return procinfo;} operator _pinfo * () const {return procinfo;}
// operator bool () const {return (int) h;} // operator bool () const {return (int) h;}
void preserve () { destroy = false; } void preserve () { destroy = false; }
void alert_parent (char); bool alert_parent (char);
bool parent_alive () { return alert_parent (__ALERT_ALIVE); }
#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

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 void __stdcall
wait_for_sigthread () wait_for_sigthread ()
{ {

View File

@ -22,8 +22,7 @@ enum
__SIGDELETE = -(NSIG + 5), __SIGDELETE = -(NSIG + 5),
__SIGFLUSHFAST = -(NSIG + 6), __SIGFLUSHFAST = -(NSIG + 6),
__SIGHOLD = -(NSIG + 7), __SIGHOLD = -(NSIG + 7),
__SIGNOHOLD = -(NSIG + 8), __SIGNOHOLD = -(NSIG + 8)
__SIGREPARENT = (NSIG + 2)
}; };
#endif #endif
@ -55,7 +54,6 @@ struct sigpacket
extern HANDLE signal_arrived; extern HANDLE signal_arrived;
extern HANDLE sigCONT; extern HANDLE sigCONT;
bool __stdcall my_parent_is_alive ();
void __stdcall sig_dispatch_pending (bool fast = false); void __stdcall sig_dispatch_pending (bool fast = false);
#ifdef _PINFO_H #ifdef _PINFO_H
extern "C" void __stdcall set_signal_mask (sigset_t newmask, sigset_t = myself->getsigmask ()); 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); ProtectHandle (cygheap->pid_handle);
else else
system_printf ("duplicate to pid_handle failed, %E"); 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 /* 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 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 the parent doesn't have to bother but what are you gonna do? Cygwin lives in
a windows world. */ 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; 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; DWORD exec_cygstarted;
if (mode == _P_OVERLAY) if (mode == _P_OVERLAY)
{ {
/* Store the old exec_cygstarted since this is used as a crude semaphore for if (!real_path.iscygexec ())
detecting when the parent has noticed the change in windows pid for this {
cygwin pid. */ /* Store the old exec_cygstarted since this is used as a crude semaphore for
exec_cygstarted = myself->cygstarted; detecting when the parent has noticed the change in windows pid for this
myself->dwProcessId = dwExeced = pi.dwProcessId; /* Reparenting needs this */ cygwin pid. */
myself.alert_parent (__SIGREPARENT); exec_cygstarted = myself->cygstarted;
myself->dwProcessId = dwExeced = pi.dwProcessId; /* Reparenting needs this */
myself.alert_parent (__ALERT_REPARENT);
}
CloseHandle (saved_sendsig); CloseHandle (saved_sendsig);
strace.execing = 1; strace.execing = 1;
hExeced = pi.hProcess; hExeced = pi.hProcess;
strcpy (myself->progname, real_path); strcpy (myself->progname, real_path); // FIXME: race?
close_all_files (); 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" 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 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). */ this). */
if (!myself->wr_proc_pipe) if (!myself->wr_proc_pipe)
{ {
@ -854,9 +859,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
else else
{ {
/* Loop, waiting for parent to notice pid change, if exec_cygstarted. /* 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) if (exec_cygstarted)
while (myself->cygstarted == exec_cygstarted) while (myself->cygstarted == exec_cygstarted && myself.parent_alive ())
low_priority_sleep (0); low_priority_sleep (0);
res = 42; res = 42;
} }