diff options
author | Christopher Faylor <me@cgf.cx> | 2004-12-05 19:41:26 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2004-12-05 19:41:26 +0000 |
commit | 54dd79bb44d2180ab769558deab274c70391cca7 (patch) | |
tree | 344f9e32353901bd9274239beb32c35ad941e414 /winsup/cygwin/sigproc.cc | |
parent | d54b79d3514106b603a2811eadf9b265e2af90d3 (diff) | |
download | cygnal-54dd79bb44d2180ab769558deab274c70391cca7.tar.gz cygnal-54dd79bb44d2180ab769558deab274c70391cca7.tar.bz2 cygnal-54dd79bb44d2180ab769558deab274c70391cca7.zip |
* sigproc.cc (mychild): Reimplement as list scan.
(proc_subproc): Don't mess with pinfo if it's myself.
* child_info.h (child_info_types): Label enum for _PROC constants.
(child_info::child_info): New constructor.
(child_info::~child_info): New destructor.
(child_info::sync): Declare new function.
(child_info_fork::child_info_fork): New constructor.
(child_info_spawn::child_info_spawn): Remove old constructor.
(child_info_spawn::child_info_spawn): New constructor.
* dcrt0.cc (dll_crt0_0): Use correct sizeof when doing sanity check on passed
in child_info. Signal readiness to parent when not forking (and not spawning).
* fork.cc (sync_with_child): Delete.
(resume_child): Remove extra argument.
(sync_with_parent): Use child_info method to sync with parent.
(fork_child): Don't close fork_info->subproc_ready since that is now handled by
the destructor.
(fork_parent): Remove subproc_ready stuff. Use child_info sync method for
waiting.. Set start time here for child. Rename "forked" to "child".
(fork): Check ch.subproc_ready for validity here.
* pinfo.h (_pinfo::exec_sendsig): Temp storage for exec stub which may be
staying around to handle non-cygwin captive process.
(_pinfo::exec_dwProcessId): Ditto.
(_pinfo::_lock): Renamed from lock.
(_pinfo::lock): New method.
(_pinfo::unlock): Ditto.
(_pinfo::initialize_lock): Ditto.
* pinfo.cc (set_myself): Use initialize_lock method to initialize myself lock.
Set "exec" fields in _pinfo to zero to indicate that we've started
successfully. Set start time here when appropriate.
(_pinfo::commune_send): Use pinfo lock/unlock methods.
(proc_waiter): Remove special case for non-cywin processes. Reinstitute
handling for PID_NOCLDSTOP.
* sigproc.cc (proc_subproc): Set proper EAGAIN errno when process table is
filled.
(sig_send): Use exec_* fields from _pinfo for sending signals if the the _pinfo
sendsig never materializes.
(child_info::child_info): New constructor, renamed from init_child_info.
Zeroes child_info structure and sets appropriate fields in structure based on
chtype.
(child_info::~child_info): New destructor. Closes subproc_ready if it exists.
(child_info_fork::child_info_fork): New constructor.
(child_info_spawn::child_info_spawn): New constructor.
(child_info::ready): New function. Signals parent when child is ready.
(child_info::sync): New function. Wait for child to signal us or process to
die.
(remove_proc): Remove closing of hProcess since this should now be handled
shortly after process creation.
* spawn.cc (spawn_guts): Use child_info_spawn constructor rather than
init_child_info. Save exec_sendsig and exec_dwProcessId in execing _pinfo.
Rely on child_info constructor to properly set parent_wr_proc_pipe in ciresrv.
Revert to previous determination on whether to start a process in suspended
mode. Remove reparenting stuff. Just keep a stub around if starting a
non-cygwin process.
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r-- | winsup/cygwin/sigproc.cc | 170 |
1 files changed, 136 insertions, 34 deletions
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index b1fea5219..d7c57b1d2 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -200,19 +200,18 @@ proc_exists (_pinfo *p) return p && !(p->process_state & (PID_EXITED | PID_ZOMBIE)); } -/* 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. */ -bool __stdcall +/* Return true if this is one of our children, false otherwise. */ +static inline bool __stdcall mychild (int pid) { - pinfo p (pid); - return p && p->ppid == myself->pid; + for (int i = 0; i < nprocs; i++) + if (procs[i]->pid == pid) + return true; + return false; } /* Handle all subprocess requests */ -#define vchild (*((pinfo *) val)) int __stdcall proc_subproc (DWORD what, DWORD val) { @@ -223,6 +222,7 @@ proc_subproc (DWORD what, DWORD val) waitq *w; #define wval ((waitq *) val) +#define vchild (*((pinfo *) val)) sigproc_printf ("args: %x, %d", what, val); @@ -244,18 +244,21 @@ proc_subproc (DWORD what, DWORD val) 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? + set_errno (EAGAIN); break; } - 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); + if (vchild != myself) + { + 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); + } procs[nprocs] = vchild; rc = procs[nprocs].wait (); if (rc) @@ -353,6 +356,8 @@ out: out1: sigproc_printf ("returning %d", rc); return rc; +#undef wval +#undef vchild } // FIXME: This is inelegant @@ -566,9 +571,27 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) sendsig = myself->sendsig; else { - for (int i = 0; !p->dwProcessId && i < 10000; i++) + HANDLE dupsig; + DWORD dwProcessId; + for (int i = 0; !p->sendsig && i < 10000; i++) low_priority_sleep (0); - HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId); + if (p->sendsig) + { + dupsig = p->sendsig; + dwProcessId = p->dwProcessId; + } + else + { + dupsig = p->exec_sendsig; + dwProcessId = p->exec_dwProcessId; + } + if (!dupsig) + { + set_errno (EAGAIN); + sigproc_printf ("sendsig handle never materialized"); + goto out; + } + HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId); if (!hp) { sigproc_printf ("OpenProcess failed, %E"); @@ -576,14 +599,12 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) goto out; } VerifyHandle (hp); - for (int i = 0; !p->sendsig && i < 10000; i++) - low_priority_sleep (0); - if (!DuplicateHandle (hp, p->sendsig, hMainProc, &sendsig, false, 0, + if (!DuplicateHandle (hp, dupsig, hMainProc, &sendsig, false, 0, DUPLICATE_SAME_ACCESS) || !sendsig) { - CloseHandle (hp); - sigproc_printf ("DuplicateHandle failed, %E"); __seterrno (); + sigproc_printf ("DuplicateHandle failed, %E"); + CloseHandle (hp); goto out; } CloseHandle (hp); @@ -695,17 +716,98 @@ out: /* Initialize some of the memory block passed to child processes by fork/spawn/exec. */ -void __stdcall -init_child_info (DWORD chtype, child_info *ch, HANDLE subproc_ready) -{ - memset (ch, 0, sizeof *ch); - ch->cb = chtype == PROC_FORK ? sizeof (child_info_fork) : sizeof (child_info); - ch->intro = PROC_MAGIC_GENERIC; - ch->magic = CHILD_INFO_MAGIC; - ch->type = chtype; - ch->subproc_ready = subproc_ready; - ch->fhandler_union_cb = sizeof (fhandler_union); - ch->user_h = cygwin_user_h; +child_info::child_info (unsigned in_cb, child_info_types chtype) +{ + memset (this, 0, in_cb); + cb = in_cb; + intro = PROC_MAGIC_GENERIC; + magic = CHILD_INFO_MAGIC; + type = chtype; + fhandler_union_cb = sizeof (fhandler_union); + user_h = cygwin_user_h; + if (chtype != PROC_SPAWN) + subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL); + sigproc_printf ("subproc_ready %p", subproc_ready); + if (chtype != PROC_EXEC && myself->wr_proc_pipe != INVALID_HANDLE_VALUE) + parent_wr_proc_pipe = myself->wr_proc_pipe; +} + +child_info::~child_info () +{ + if (subproc_ready) + CloseHandle (subproc_ready); +} + +child_info_fork::child_info_fork () : + child_info (sizeof *this, _PROC_FORK) +{ +} + +child_info_spawn::child_info_spawn (child_info_types chtype) : + child_info (sizeof *this, chtype) +{ +} + +void +child_info::ready (bool execed) +{ + if (!subproc_ready) + { + sigproc_printf ("subproc_ready not set"); + return; + } + + if (!SetEvent (subproc_ready)) + api_fatal ("SetEvent failed"); + else + sigproc_printf ("signalled %p that I was ready", subproc_ready); + + if (execed) + { + CloseHandle (subproc_ready); + subproc_ready = NULL; + } +} + +bool +child_info::sync (pinfo& vchild, DWORD howlong) +{ + if (!subproc_ready) + { + sigproc_printf ("not waiting. subproc_ready is NULL"); + return false; + } + + HANDLE w4[2]; + w4[0] = subproc_ready; + w4[1] = vchild.hProcess; + + bool res; + sigproc_printf ("waiting for subproc_ready(%p) and child process(%p)", w4[0], w4[1]); + switch (WaitForMultipleObjects (2, w4, FALSE, howlong)) + { + case WAIT_OBJECT_0: + sigproc_printf ("got subproc_ready for pid %d", vchild->pid); + res = true; + break; + case WAIT_OBJECT_0 + 1: + if (WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0) + sigproc_printf ("should never happen. noticed subproc_ready after process exit"); + else + { + DWORD exitcode = 0; + (void) GetExitCodeProcess (vchild.hProcess, &exitcode); + vchild->exitcode = (exitcode & 0xff) << 8; + sigproc_printf ("non-cygwin exit value is %p", exitcode); + } + res = false; + break; + default: + system_printf ("wait failed, pid %d, %E", vchild->pid); + res = false; + break; + } + return res; } /* Check the state of all of our children to see if any are stopped or |