* 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.
This commit is contained in:
Christopher Faylor
2004-12-05 19:41:26 +00:00
parent d54b79d351
commit 54dd79bb44
9 changed files with 501 additions and 376 deletions

View File

@@ -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)
child_info::child_info (unsigned in_cb, child_info_types chtype)
{
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;
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