summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/sigproc.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2004-12-05 19:41:26 +0000
committerChristopher Faylor <me@cgf.cx>2004-12-05 19:41:26 +0000
commit54dd79bb44d2180ab769558deab274c70391cca7 (patch)
tree344f9e32353901bd9274239beb32c35ad941e414 /winsup/cygwin/sigproc.cc
parentd54b79d3514106b603a2811eadf9b265e2af90d3 (diff)
downloadcygnal-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.cc170
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