summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/sigproc.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2004-11-26 04:15:10 +0000
committerChristopher Faylor <me@cgf.cx>2004-11-26 04:15:10 +0000
commit8cb359d9470bc114ea767c99ab65bf603903f150 (patch)
tree23617beea2a909e44cc60e7dbb3594494600388f /winsup/cygwin/sigproc.cc
parentc1ab3396dc48a9bf00e7e6235998c437b5754f89 (diff)
downloadcygnal-8cb359d9470bc114ea767c99ab65bf603903f150.tar.gz
cygnal-8cb359d9470bc114ea767c99ab65bf603903f150.tar.bz2
cygnal-8cb359d9470bc114ea767c99ab65bf603903f150.zip
* child_info.h (child_info_spawn::hexec_proc): Eliminate.
* dcrt0.cc (dll_crt0_0): Remove hexec_proc stuff. * fork.cc (fork_child): Remove call to pinfo_fixup_after_fork. * pinfo.cc (set_myself): Close and zero pid_handle if set. (pinfo_fixup_after_fork): Delete. (proc_waiter): Don't close vchild.hProcess here. Do that when we are remove the vchild from procs. Save hProcess as pid_handle only on first reparent operation. (pinfo::wait): Don't set pid_handle here. (pinfo::alert_parent): Always try to send signal. If unsuccessful then close and zero wr_proc_pipe. * pinfo.h (pinfo::pinfo): Make sure that appropriate parts of the class are zeroed on construction. (pinfo::alert_parent): Take char argument. (pinfo_fixup_after_fork): Delete declaration. (hexec_proc): Ditto. * sigproc.cc (remove_proc): Close pid_handle and hProcess if appropriate. * spawn.cc (spawn_guts): Set cygheap->pid_handle on first exec. * cygheap.h (init_cygheap::pid_handle): New element. * pinfo.cc (set_myself): Clear previously existing cygheap->pid_handle when a new process has been started. (pinfo::wait): Make sure that a handle to the newly forked/spawned process is kept around so that the pid will not be reused. * pinfo.h (_pinfo::pid_handle): Move. (pinfo::pid_handle): to here. * spawn.cc (spawn_guts): Create a pid_handle in cygheap prior to spawning to ensure that the pid does not get reused during the lifetime of the "cygwin pid". * pinfo.h (pinfo::alert_parent): New function. * exceptions.cc (sig_handle_tty_stop): Use alert_parent to send "signals" to parent. * fork.cc (fork_parent): Don't close pi.hProcess. Let the waiter thread do that. * pinfo.cc (proc_waiter): Detect case where process exits without setting the exit code and use value from GetExitCodeProcess. Reluctantly implement __SIGREPARENT. (pinfo::alert_parent): Define. * sigproc.h (__SIGREPARENT): New enum. * spawn.cc (spawn_guts): Send reparent signal to parent on exec. Always create process in suspended state to avoid races. Remove cygthread.h in favor of cygtls.h throughout since cygtls now includes cygthread.h. Eliminate ppid_handle usage throughout. * child_info.h: Regenerate magic number (child_info): Remove pppid_handle. * cygthread.h (cygthread::release): New method. Frees thread without waiting. * cygthread.cc (cygthread::stub): Set _ctinfo in _mytls to point to information for executing thread. Don't call SetEvent if thread is no longer in use. (cygthread::simplestub): Ditto. * cygtls.h (_cygtls::_ctinfo): New element contains pointer to information about executing cygthread, if any. * dcrt0.cc: Remove last vestiges of per_thread stuff. (dll_crt0_0): Ditto. Remove accommodation for ppid_handle. (do_exit): Remove obsolete reparenting test. (_exit): Exit with a more SUSv3-like exit value. * dtable.cc (dtable::stdio_init): Check for myself->cygstarted rather than myself->ppid_handle to see if we were started by a cygwin process. * exceptions.cc (open_stackdumpfile): Ditto. (handle_exceptions): Ditto. (ctrl_c_handler): Ditto. (sig_handle_tty_stop): Ditto. Let parent send signal to itself on STOP. (sigpacket::process): Comment out vfork test. (signal_exit): Use more SUSv3-like exit value on signal. * external.cc (fillout_pinfo): Don't set hProcess. * fork.cc: Remove VFORK cruft. (per_thread::set): Delete. (fork_child): Remove perthread stuff. (fork_parent): Remove obsolete subproc_init. Accommodate new method for tracking subprocesses. * pinfo.cc (set_myself): Accommodate new pinfo/_pinfo layout. Set some things here that used to be set in wait_sig. (_pinfo::exit): Set exitcode here. Close process pipe. (_pinfo::commune_send): Accommodeate new pinfo/_pinfo layout. (proc_waiter): New function. Waits, in a thread for subprocess to go away. (pinfo::wait): New function. Initialization for proc_waiter. * pinfo.h (_pinfo::exitcode): New element. (_pinfo::cygstarted): Ditto. (_pinfo::wr_proc_pipe): Ditto. (_pinfo::ppid_handle): Delete. (_pinfo::hProcess): Delete. (_pinfo::lock): Delete. (pinfo::hProcess): New element. (pinfo::lock): Ditto. (pinfo::wait): Declare new function. (pinfo::preserve): Define new function. * sigproc.cc: Remove old stuff from wait_subproc thread based method. (zombies): Remove. (procs): New. (my_parent_is_alive): Just check that the parent pid exists. (mychild): Just use pinfo methods to determine if child is mine. (proc_subproc): Revamp PROC_ADDCHILD to use pinfo::wait. Remove PROC_CHILDTERMINATED logic. Use different method to remove processes from list when SIGCHLD == SIG_IGN. (proc_terminate): Gut. (subproc_init): Delete. (init_child_info): Remove setting of pppid_handle. (checkstate): Revamp to only scan procs array. (remove_proc): Rename from remove_zombie. Don't close hProcess or pid_handle. Don't release memory if it's myself. (stopped_or_terminated): Change logic to handle new consolidated proc/zombie array. (wait_subproc): Delete. * sigproc.h: Remove obsolete EXIT_* defines. (subproc_init): Remove declaration. * spawn.cc (spawn_guts): Remove reparenting stuff. Use standard wait logic to wait for child if started from a non-cygwin process. * tlsoffsets.h: Regenerate. * tty.cc (tty_init): Check for myself->cygstarted rather than myself->ppid_handle to see if we were started by a cygwin process. * include/sys/signal.h (external_pinfo::exitcode): Replace hProcess. * include/sys/wait.h (WCOREDUMP): Define. * fhandler_tty.cc (fhandler_tty_slave::read): Add debugging output for timeout case. * signal.cc (abort): Flag that we are exiting with the ABORT signal.
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r--winsup/cygwin/sigproc.cc478
1 files changed, 105 insertions, 373 deletions
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 416761ee6..844e80a2b 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -28,10 +28,8 @@ details. */
#include "cygheap.h"
#include "child_info_magic.h"
#include "shared_info.h"
-#include "cygthread.h"
#include "cygtls.h"
#include "sigproc.h"
-#include "perthread.h"
#include "exceptions.h"
/*
@@ -42,11 +40,9 @@ details. */
#define PSIZE 63 // Number of processes
-#define wake_wait_subproc() SetEvent (events[0])
-
#define no_signals_available() (!hwait_sig || (myself->sendsig == INVALID_HANDLE_VALUE) || exit_state)
-#define NZOMBIES 256
+#define NPROCS 256
/*
* Global variables
@@ -64,30 +60,15 @@ HANDLE NO_COPY signal_arrived; // Event signaled when a signal has
#define Static static NO_COPY
-/* How long to wait for message/signals. Normally this is infinite.
- On termination, however, these are set to zero as a flag to exit. */
-
-Static DWORD proc_loop_wait = 1000; // Wait for subprocesses to exit
-
HANDLE NO_COPY sigCONT; // Used to "STOP" a process
Static cygthread *hwait_sig; // Handle of wait_sig thread
-Static cygthread *hwait_subproc; // Handle of sig_subproc thread
Static HANDLE wait_sig_inited; // Control synchronization of
// message queue startup
-/* Used by WaitForMultipleObjects. These are handles to child processes.
- */
-Static HANDLE events[PSIZE + 1]; // All my children's handles++
-#define hchildren (events + 1) // Where the children handles begin
-Static int nchildren; // Number of active children
-Static char cpchildren[PSIZE * sizeof (pinfo)]; // All my children info
-Static int nzombies; // Number of deceased children
-Static char czombies[(NZOMBIES + 1) * sizeof (pinfo)]; // All my deceased children info
-
-#define pchildren ((pinfo *) cpchildren)
-#define zombies ((pinfo *) czombies)
-
+Static int nprocs; // Number of deceased children
+Static char cprocs[(NPROCS + 1) * sizeof (pinfo)]; // All my deceased children info
+#define procs ((pinfo *) cprocs)
Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
muto NO_COPY *sync_proc_subproc = NULL; // Control access to subproc stuff
@@ -97,9 +78,8 @@ DWORD NO_COPY sigtid = 0; // ID of the signal thread
/* Function declarations */
static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
static __inline__ bool get_proc_lock (DWORD, DWORD);
-static void __stdcall remove_zombie (int);
-static int __stdcall stopped_or_terminated (waitq *, _pinfo *);
-static DWORD WINAPI wait_subproc (VOID *);
+static bool __stdcall remove_proc (int);
+static bool __stdcall stopped_or_terminated (waitq *, _pinfo *);
static DWORD WINAPI wait_sig (VOID *arg);
/* wait_sig bookkeeping */
@@ -152,33 +132,13 @@ bool __stdcall
my_parent_is_alive ()
{
bool res;
- if (!myself->ppid_handle)
+ if (myself->cygstarted)
+ res = pid_exists (myself->ppid);
+ else
{
- debug_printf ("No myself->ppid_handle");
+ debug_printf ("Not started by cygwin app");
res = false;
}
- else
- for (int i = 0; i < 2; i++)
- switch (res = WaitForSingleObject (myself->ppid_handle, 0))
- {
- case WAIT_OBJECT_0:
- debug_printf ("parent dead.");
- res = false;
- goto out;
- case WAIT_TIMEOUT:
- debug_printf ("parent still alive");
- res = true;
- goto out;
- case WAIT_FAILED:
- DWORD werr = GetLastError ();
- if (werr == ERROR_INVALID_HANDLE && i == 0)
- continue;
- system_printf ("WFSO for myself->ppid_handle(%p) failed, error %d",
- myself->ppid_handle, werr);
- res = false;
- goto out;
- }
-out:
return res;
}
@@ -193,7 +153,7 @@ wait_for_sigthread ()
}
/* Get the sync_proc_subproc muto to control access to
- * children, zombie arrays.
+ * children, proc arrays.
* Attempt to handle case where process is exiting as we try to grab
* the mutex.
*/
@@ -260,16 +220,11 @@ proc_exists (_pinfo *p)
/* Return 1 if this is one of our children, zero otherwise.
FIXME: This really should be integrated with the rest of the proc_subproc
testing. Scanning these lists twice is inefficient. */
-int __stdcall
+bool __stdcall
mychild (int pid)
{
- for (int i = 0; i < nchildren; i++)
- if (pchildren[i]->pid == pid)
- return 1;
- for (int i = 0; i < nzombies; i++)
- if (zombies[i]->pid == pid)
- return 1;
- return 0;
+ pinfo p (pid);
+ return p && p->ppid == myself->pid;
}
/* Handle all subprocess requests
@@ -283,7 +238,6 @@ proc_subproc (DWORD what, DWORD val)
_pinfo *child;
int clearing;
waitq *w;
- int thiszombie;
#define wval ((waitq *) val)
@@ -301,84 +255,32 @@ proc_subproc (DWORD what, DWORD val)
* (usually called from the main thread)
*/
case PROC_ADDCHILD:
- if (nchildren >= PSIZE - 1)
+ /* Filled up process table? */
+ if (nprocs >= NPROCS)
{
+ sigproc_printf ("proc table overflow: hit %d processes, pid %d\n",
+ nprocs, vchild->pid);
rc = 0;
+ set_errno (EMFILE); // FIXMENOW - what's the right errno?
break;
}
- pchildren[nchildren] = vchild;
- hchildren[nchildren] = vchild->hProcess;
- if (!DuplicateHandle (hMainProc, vchild->hProcess, hMainProc, &vchild->pid_handle,
- 0, 0, DUPLICATE_SAME_ACCESS))
- system_printf ("Couldn't duplicate child handle for pid %d, %E", vchild->pid);
- ProtectHandle1 (vchild->pid_handle, pid_handle);
-
- if (!DuplicateHandle (hMainProc, hMainProc, vchild->hProcess, &vchild->ppid_handle,
- SYNCHRONIZE | PROCESS_DUP_HANDLE, TRUE, 0))
- system_printf ("Couldn't duplicate my handle<%p> for pid %d, %E", hMainProc, vchild->pid);
+
vchild->ppid = myself->pid;
vchild->uid = myself->uid;
vchild->gid = myself->gid;
vchild->pgid = myself->pgid;
vchild->sid = myself->sid;
vchild->ctty = myself->ctty;
+ vchild->cygstarted = true;
vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY);
-
- sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p",
- vchild->pid, nchildren, vchild->dwProcessId,
- vchild->hProcess);
- nchildren++;
-
- wake_wait_subproc ();
- break;
-
- /* A child process had terminated.
- Possibly this is just due to an exec(). Cygwin implements an exec()
- as a "handoff" from one windows process to another. If child->hProcess
- is different from what is recorded in hchildren, then this is an exec().
- Otherwise this is a normal child termination event.
- (called from wait_subproc thread) */
- case PROC_CHILDTERMINATED:
- if (hchildren[val] != pchildren[val]->hProcess)
- {
- sigproc_printf ("pid %d[%d], reparented old hProcess %p, new %p",
- pchildren[val]->pid, val, hchildren[val], pchildren[val]->hProcess);
- HANDLE h = hchildren[val];
- hchildren[val] = pchildren[val]->hProcess; /* Filled out by child */
- ForceCloseHandle1 (h, childhProc);
- ProtectHandle1 (pchildren[val]->hProcess, childhProc);
- rc = 0;
- goto out; // This was an exec()
- }
-
- sigproc_printf ("pid %d[%d] terminated, handle %p, nchildren %d, nzombies %d",
- pchildren[val]->pid, val, hchildren[val], nchildren, nzombies);
-
- thiszombie = nzombies;
- zombies[nzombies] = pchildren[val]; // Add to zombie array
- zombies[nzombies++]->process_state = PID_ZOMBIE;// Walking dead
-
- sigproc_printf ("zombifying [%d], pid %d, handle %p, nchildren %d",
- val, pchildren[val]->pid, hchildren[val], nchildren);
- if ((int) val < --nchildren)
- {
- hchildren[val] = hchildren[nchildren];
- pchildren[val] = pchildren[nchildren];
- }
-
- /* See if we should care about the this terminated process. If we've
- filled up our table or if we're ignoring SIGCHLD, then we immediately
- remove the process and move on. Otherwise, this process becomes a zombie
- which must be reaped by a wait() call. FIXME: This is a very inelegant
- way to deal with this and could lead to process hangs. */
- if (nzombies >= NZOMBIES)
+ procs[nprocs] = vchild;
+ rc = procs[nprocs].wait ();
+ if (rc)
{
- sigproc_printf ("zombie table overflow %d", thiszombie);
- remove_zombie (thiszombie);
+ sigproc_printf ("added pid %d to proc table, slot %d", vchild->pid,
+ nprocs);
+ nprocs++;
}
-
- /* Don't scan the wait queue yet. Caller will send SIGCHLD to this process.
- This will cause an eventual scan of waiters. */
break;
/* Handle a wait4() operation. Allocates an event for the calling
@@ -401,8 +303,8 @@ proc_subproc (DWORD what, DWORD val)
*/
if ((wval->ev = wval->thread_ev) == NULL)
{
- wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE,
- FALSE, NULL);
+ wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, FALSE,
+ NULL);
ProtectHandle1 (wval->ev, wq_ev);
}
@@ -459,9 +361,8 @@ proc_subproc (DWORD what, DWORD val)
}
if (global_sigs[SIGCHLD].sa_handler == (void *) SIG_IGN)
- while (nzombies)
- remove_zombie (0);
- break;
+ for (int i = 0; i < nprocs; i += remove_proc (i))
+ continue;
}
out:
@@ -492,54 +393,29 @@ _cygtls::remove_wq (DWORD wait)
* Called on process exit.
* Also called by spawn_guts to disassociate any subprocesses from this
* process. Subprocesses will then know to clean up after themselves and
- * will not become zombies.
+ * will not become procs.
*/
void __stdcall
proc_terminate (void)
{
- sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies);
+ sigproc_printf ("nprocs %d", nprocs);
/* Signal processing is assumed to be blocked in this routine. */
- if (hwait_subproc)
+ if (nprocs)
{
- proc_loop_wait = 0; // Tell wait_subproc thread to exit
sync_proc_subproc->acquire (WPSP);
- wake_wait_subproc (); // Wake wait_subproc loop
- hwait_subproc = NULL;
(void) proc_subproc (PROC_CLEARWAIT, 1);
- /* Clean out zombie processes from the pid list. */
+ /* Clean out proc processes from the pid list. */
int i;
- for (i = 0; i < nzombies; i++)
- {
- if (zombies[i]->hProcess)
- {
- ForceCloseHandle1 (zombies[i]->hProcess, childhProc);
- ForceCloseHandle1 (zombies[i]->pid_handle, pid_handle);
- }
- zombies[i]->ppid = 1;
- zombies[i]->process_state = PID_EXITED; /* CGF FIXME - still needed? */
- zombies[i].release (); // FIXME: this breaks older gccs for some reason
- }
-
- /* Disassociate my subprocesses */
- for (i = 0; i < nchildren; i++)
+ for (i = 0; i < nprocs; i++)
{
- if (!pchildren[i]->hProcess)
- sigproc_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid,
- pchildren[i]->dwProcessId);
- else
- {
- ForceCloseHandle1 (pchildren[i]->hProcess, childhProc);
- sigproc_printf ("%d(%d) closed child handle", pchildren[i]->pid,
- pchildren[i]->dwProcessId);
- pchildren[i]->ppid = 1;
- if (pchildren[i]->pgid == myself->pid)
- pchildren[i]->process_state |= PID_ORPHANED;
- }
- pchildren[i].release ();
+ procs[i]->ppid = 1;
+ if (!proc_exists (procs[i]))
+ procs[i]->process_state = PID_EXITED; /* CGF FIXME - still needed? */
+ procs[i].release ();
}
- nchildren = nzombies = 0;
+ nprocs = 0;
sync_proc_subproc->release ();
}
sigproc_printf ("leaving");
@@ -610,7 +486,7 @@ sigproc_init ()
ProtectHandle (wait_sig_inited);
/* sync_proc_subproc is used by proc_subproc. It serialises
- * access to the children and zombie arrays.
+ * access to the children and proc arrays.
*/
new_muto (sync_proc_subproc);
@@ -648,7 +524,7 @@ sigproc_terminate (void)
CloseHandle (sendsig);
}
}
- proc_terminate (); // Terminate process handling thread
+ proc_terminate (); // clean up process stuff
return;
}
@@ -833,25 +709,6 @@ out:
return rc;
}
-/* Initialize the wait_subproc thread.
- * Called from fork() or spawn() to initialize the handling of subprocesses.
- */
-void __stdcall
-subproc_init (void)
-{
- if (hwait_subproc)
- return;
-
- /* A "wakeup" handle which can be toggled to make wait_subproc reexamine
- * the hchildren array.
- */
- events[0] = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
- hwait_subproc = new cygthread (wait_subproc, NULL, "proc");
- hwait_subproc->zap_h ();
- ProtectHandle (events[0]);
- sigproc_printf ("started wait_subproc thread");
-}
-
/* Initialize some of the memory block passed to child processes
by fork/spawn/exec. */
@@ -864,7 +721,6 @@ init_child_info (DWORD chtype, child_info *ch, HANDLE subproc_ready)
ch->magic = CHILD_INFO_MAGIC;
ch->type = chtype;
ch->subproc_ready = subproc_ready;
- ch->pppid_handle = myself->ppid_handle;
ch->fhandler_union_cb = sizeof (fhandler_union);
ch->user_h = cygwin_user_h;
}
@@ -877,132 +733,107 @@ checkstate (waitq *parent_w)
{
int potential_match = 0;
- sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies);
+ sigproc_printf ("nprocs %d", nprocs);
/* Check already dead processes first to see if they match the criteria
- * given in w->next.
- */
- for (int i = 0; i < nzombies; i++)
- switch (stopped_or_terminated (parent_w, zombies[i]))
+ * given in w->next. */
+ int res;
+ for (int i = 0; i < nprocs; i++)
+ if ((res = stopped_or_terminated (parent_w, procs[i])))
{
- case -1:
- potential_match = -1;
- break;
- case 1:
- remove_zombie (i);
+ remove_proc (i);
potential_match = 1;
goto out;
}
- sigproc_printf ("checking alive children");
-
- /* No dead terminated children matched. Check for stopped children. */
- for (int i = 0; i < nchildren; i++)
- switch (stopped_or_terminated (parent_w, pchildren[i]))
- {
- case -1:
- potential_match = -1;
- break;
- case 1:
- potential_match = 1;
- goto out;
- }
+ sigproc_printf ("no matching terminated children found");
+ potential_match = -!!nprocs;
out:
sigproc_printf ("returning %d", potential_match);
return potential_match;
}
-/* Remove a zombie from zombies by swapping it with the last child in the list.
- */
-static void __stdcall
-remove_zombie (int ci)
+/* Remove a proc from procs by swapping it with the last child in the list.
+ Also releases shared memory of exited processes. */
+static bool __stdcall
+remove_proc (int ci)
{
- sigproc_printf ("removing %d, pid %d, nzombies %d", ci, zombies[ci]->pid,
- nzombies);
+ if (proc_exists (procs[ci]))
+ return true;
- if (zombies[ci])
+ sigproc_printf ("removing procs[%d], pid %d, nprocs %d", ci, procs[ci]->pid,
+ nprocs);
+ if (procs[ci] != myself)
{
- ForceCloseHandle1 (zombies[ci]->hProcess, childhProc);
- ForceCloseHandle1 (zombies[ci]->pid_handle, pid_handle);
- zombies[ci].release ();
+ procs[ci].release ();
+ if (procs[ci].pid_handle)
+ ForceCloseHandle1 (procs[ci].pid_handle, childhProc);
+ if (procs[ci].hProcess)
+ ForceCloseHandle1 (procs[ci].hProcess, childhProc);
}
-
- if (ci < --nzombies)
- zombies[ci] = zombies[nzombies];
-
- return;
+ if (ci < --nprocs)
+ procs[ci] = procs[nprocs];
+ return 0;
}
/* Check status of child process vs. waitq member.
- *
- * parent_w is the pointer to the parent of the waitq member in question.
- * child is the subprocess being considered.
- *
- * Returns
- * 1 if stopped or terminated child matches parent_w->next criteria
- * -1 if a non-stopped/terminated child matches parent_w->next criteria
- * 0 if child does not match parent_w->next criteria
- */
-static int __stdcall
+
+ parent_w is the pointer to the parent of the waitq member in question.
+ child is the subprocess being considered.
+
+ Returns non-zero if waiting thread released. */
+static bool __stdcall
stopped_or_terminated (waitq *parent_w, _pinfo *child)
{
- int potential_match;
+ int might_match;
waitq *w = parent_w->next;
sigproc_printf ("considering pid %d", child->pid);
if (w->pid == -1)
- potential_match = 1;
+ might_match = 1;
else if (w->pid == 0)
- potential_match = child->pgid == myself->pgid;
+ might_match = child->pgid == myself->pgid;
else if (w->pid < 0)
- potential_match = child->pgid == -w->pid;
+ might_match = child->pgid == -w->pid;
else
- potential_match = (w->pid == child->pid);
+ might_match = (w->pid == child->pid);
- if (!potential_match)
+ if (!might_match)
return 0;
- bool terminated;
+ int terminated;
- if ((terminated = child->process_state == PID_ZOMBIE) ||
- ((w->options & WUNTRACED) && child->stopsig))
- {
- parent_w->next = w->next; /* successful wait. remove from wait queue */
- w->pid = child->pid;
+ if (!((terminated = (child->process_state == PID_ZOMBIE)) ||
+ ((w->options & WUNTRACED) && child->stopsig)))
+ return 0;
- if (!terminated)
- {
- sigproc_printf ("stopped child");
- w->status = (child->stopsig << 8) | 0x7f;
- child->stopsig = 0;
- }
- else /* Should only get here when child has been moved to the zombies array */
- {
- DWORD status;
- if (!GetExitCodeProcess (child->hProcess, &status))
- status = 0xffff;
- if (status & EXIT_SIGNAL)
- w->status = (status >> 8) & 0xff; /* exited due to signal */
- else
- w->status = (status & 0xff) << 8; /* exited via "exit ()" */
+ parent_w->next = w->next; /* successful wait. remove from wait queue */
+ w->pid = child->pid;
- add_rusage (&myself->rusage_children, &child->rusage_children);
- add_rusage (&myself->rusage_children, &child->rusage_self);
+ if (!terminated)
+ {
+ sigproc_printf ("stopped child");
+ w->status = (child->stopsig << 8) | 0x7f;
+ child->stopsig = 0;
+ }
+ else /* Should only get here when child has been moved to the procs array */
+ {
+ w->status = child->exitcode;
- if (w->rusage)
- {
- add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
- add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
- }
- }
+ add_rusage (&myself->rusage_children, &child->rusage_children);
+ add_rusage (&myself->rusage_children, &child->rusage_self);
- if (!SetEvent (w->ev)) /* wake up wait4 () immediately */
- system_printf ("couldn't wake up wait event %p, %E", w->ev);
- return 1;
+ if (w->rusage)
+ {
+ add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
+ add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
+ }
}
- return -potential_match;
+ if (!SetEvent (w->ev)) /* wake up wait4 () immediately */
+ system_printf ("couldn't wake up wait event %p, %E", w->ev);
+ return true;
}
static void
@@ -1078,27 +909,10 @@ wait_sig (VOID *self)
signals. Prior to this, dwProcessId was set to the windows pid of
of the original windows process which spawned us unless this was a
"toplevel" process. */
- myself->dwProcessId = GetCurrentProcessId ();
myself->process_state |= PID_ACTIVE;
myself->process_state &= ~PID_INITIALIZING;
sigproc_printf ("myself->dwProcessId %u", myself->dwProcessId);
- /* If we've been execed, then there is still a stub left in the previous
- windows process waiting to see if it's started a cygwin process or not.
- Signalling subproc_ready indicates that we are a cygwin process. */
- if (child_proc_info && child_proc_info->type == PROC_EXEC)
- {
- debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
- if (!SetEvent (child_proc_info->subproc_ready))
- system_printf ("SetEvent (subproc_ready) failed, %E");
- ForceCloseHandle1 (child_proc_info->subproc_ready, subproc_ready);
- /* Initialize an "indirect" pid block so that if someone looks up this
- process via its Windows PID it will be redirected to the appropriate
- Cygwin PID shared memory block. */
- static pinfo NO_COPY myself_identity;
- myself_identity.init (cygwin_pid (myself->dwProcessId), PID_EXECED);
- }
-
SetEvent (wait_sig_inited);
sigtid = GetCurrentThreadId ();
@@ -1215,85 +1029,3 @@ wait_sig (VOID *self)
sigproc_printf ("done");
ExitThread (0);
}
-
-/* Wait for subprocesses to terminate. Executes in a separate thread. */
-static DWORD WINAPI
-wait_subproc (VOID *)
-{
- sigproc_printf ("starting");
- int errloop = 0;
-
- for (;;)
- {
- DWORD rc = WaitForMultipleObjects (nchildren + 1, events, FALSE,
- proc_loop_wait);
- if (!proc_loop_wait)
- break;
- if (rc == WAIT_TIMEOUT)
- continue;
-
- if (rc == WAIT_FAILED)
- {
- /* It's ok to get an ERROR_INVALID_HANDLE since another thread may have
- closed a handle in the children[] array. So, we try looping a couple
- of times to stabilize. FIXME - this is not foolproof. Probably, this
- thread should be responsible for closing the children. */
- if (!errloop++)
- proc_subproc (PROC_NOTHING, 0); // Just synchronize and continue
- if (errloop < 10)
- continue;
-
- system_printf ("wait failed. nchildren %d, wait %d, %E",
- nchildren, proc_loop_wait);
-
- for (int i = 0; i <= nchildren; i++)
- if ((rc = WaitForSingleObject (events[i], 0)) == WAIT_OBJECT_0 ||
- rc == WAIT_TIMEOUT)
- continue;
- else if (i == 0)
- system_printf ("nchildren %d, event[%d] %p, %E", nchildren, i, events[i]);
- else
- {
- system_printf ("nchildren %d, event[%d] %p, pchildren[%d] %p, events[0] %p, %E",
- nchildren, i, events[i], i - 1, (_pinfo *) pchildren[i - 1], events[0]);
- system_printf ("pid %d, dwProcessId %u, hProcess %p, progname '%s'",
- pchildren[i - 1]->pid, pchildren[i - 1]->dwProcessId,
- pchildren[i - 1]->hProcess, pchildren[i - 1]->progname);
- }
- break;
- }
-
- errloop = 0;
- rc -= WAIT_OBJECT_0;
- if (rc-- != 0)
- {
- siginfo_t si;
- si.si_signo = SIGCHLD;
- si.si_code = SI_KERNEL;
- si.si_pid = pchildren[rc]->pid;
- si.si_uid = pchildren[rc]->uid;
- si.si_errno = 0;
- GetExitCodeProcess (hchildren[rc], (DWORD *) &si.si_status);
-#if 0 // FIXME: This is tricky to get right
- si.si_utime = pchildren[rc]->rusage_self.ru_utime;
- si.si_stime = pchildren[rc].rusage_self.ru_stime;
-#else
- si.si_utime = 0;
- si.si_stime = 0;
-#endif
- rc = proc_subproc (PROC_CHILDTERMINATED, rc);
-
- /* Send a SIGCHLD to myself. We do this here, rather than in proc_subproc
- to avoid the proc_subproc lock since the signal thread will eventually
- be calling proc_subproc and could unnecessarily block. */
- if (rc)
- sig_send (myself_nowait, si);
- }
- sigproc_printf ("looping");
- }
-
- ForceCloseHandle (events[0]);
- events[0] = NULL;
- sigproc_printf ("done");
- ExitThread (0);
-}