From 82b7b4fd4fba28d054161f104f6bd8471f73ab14 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Fri, 3 Dec 2004 04:46:00 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 20 ++++++++++++++++++++ winsup/cygwin/child_info.h | 3 ++- winsup/cygwin/fork.cc | 2 ++ winsup/cygwin/pinfo.cc | 33 +++++++++++++++++++-------------- winsup/cygwin/pinfo.h | 9 ++++++++- winsup/cygwin/sigproc.cc | 17 ----------------- winsup/cygwin/sigproc.h | 4 +--- winsup/cygwin/spawn.cc | 29 +++++++++++++++++------------ 8 files changed, 69 insertions(+), 48 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b8b620e57..82e41ce5f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,23 @@ +2004-12-02 Christopher Faylor + + * 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 + + * 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 * pinfo.cc (pinfo::wait): Use better name for cygthread. diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h index 7cbcb6fa5..48186e67c 100644 --- a/winsup/cygwin/child_info.h +++ b/winsup/cygwin/child_info.h @@ -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; }; diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 1dc1e7b8e..4744202af 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -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); diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index a5eb4807f..62dd63d5d 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -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 diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index b062934da..e1d5d35f6 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -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 diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 844e80a2b..b1fea5219 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -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 () { diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 9c7807a49..9a432d31f 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -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 ()); diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 426ee119f..4eb231efd 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -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; }