* child_info.h (CURR_CHILD_INFO_MAGIC): Update.

(child_info::parent_wr_proc_pipe): Eliminate.
* pinfo.h (_pinfo::alert_parent): Move here from pinfo class.
(_pinfo::dup_proc_pipe): New method.
(_pinfo::sync_proc_pipe): Ditto.
* exceptions.cc (sig_handle_tty_stop): Reflect move of alert_parent.
* init.cc (dll_entry): Exit with status one if main process called ExitProcess.
* pinfo.cc (set_myself): Remove handling of parent_wr_proc_pipe.
(_pinfo::exit): Reflect move of alert_parent.  Set procinfo to NULL to flag
that we are exiting normally.  Always use exitcode when exiting
(although this could be a little racy).
(pinfo::init): Set default exit to SIGTERM.  This will be the exit code
reported if process is terminated.
(_pinfo::dup_proc_pipe): New function.
(pinfo::wait): Duplicate wr_proc_pipe to the right place.  Use dup_proc_pipe to
move the pipe to the child.
(_pinfo::sync_proc_pipe): New function.
(_pinfo::alert_parent): Move to _pinfo.  Make sure that wr_proc_pipe is ours
before using it.
* sigproc.cc (child_info::child_info): Remove handling of parent_wr_proc_pipe.
* spawn.cc (spawn_guts): Pass our wr_proc_pipe to the child when execing.
Ensure that exit code of cygwin process started from windows is correctly set.
This commit is contained in:
Christopher Faylor
2004-12-24 18:31:23 +00:00
parent 4697fbcd51
commit e1736c2f13
8 changed files with 121 additions and 66 deletions

View File

@@ -44,8 +44,6 @@ 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);
@@ -68,19 +66,11 @@ set_myself (HANDLE h)
}
else if (!myself->wr_proc_pipe)
myself->start_time = time (NULL); /* Register our starting time. */
else
else if (cygheap->pid_handle)
{
/* We've inherited the parent's wr_proc_pipe. We don't need it,
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;
}
ForceCloseHandle (cygheap->pid_handle);
cygheap->pid_handle = NULL;
}
# undef child_proc_info
return;
}
@@ -117,9 +107,9 @@ _pinfo::exit (UINT n, bool norecord)
exit_state = ES_FINAL;
cygthread::terminate ();
if (norecord)
sigproc_terminate (); /* Just terminate signal and process stuff */
sigproc_terminate (); /* Just terminate signal and process stuff */
else
exitcode = n; /* We're really exiting. Record the UNIX exit code. */
exitcode = n; /* We're really exiting. Record the UNIX exit code. */
if (this)
{
@@ -135,7 +125,7 @@ _pinfo::exit (UINT n, bool norecord)
/* We could just let this happen automatically when the process
exits but this should gain us a microsecond or so by notifying
the parent early. */
myself.alert_parent (0);
myself->alert_parent (0);
}
}
@@ -143,7 +133,8 @@ _pinfo::exit (UINT n, bool norecord)
sigproc_printf ("Calling ExitProcess %d", n);
_my_tls.stacklock = 0;
_my_tls.stackptr = _my_tls.stack;
ExitProcess (n);
myself.procinfo = NULL; // This breaks the abstraction a little doesn't it?
ExitProcess (exitcode);
}
void
@@ -273,7 +264,10 @@ pinfo::init (pid_t n, DWORD flag, HANDLE in_h)
if (!created)
/* nothing */;
else if (!(flag & PID_EXECED))
procinfo->pid = n;
{
procinfo->pid = n;
procinfo->exitcode = SIGTERM;
}
else
{
procinfo->process_state |= PID_IN_USE | PID_EXECED;
@@ -664,15 +658,10 @@ _pinfo::cmdline (size_t& n)
}
/* This is the workhorse which waits for the write end of the pipe
created during new process creation. If the pipe is closed, it is
assumed that the cygwin pid has exited. Otherwise, various "signals"
can be sent to the parent to inform the parent to perform a certain
action.
This code was originally written to eliminate the need for "reparenting"
but, unfortunately, reparenting is still needed in order to get the
exit code of an execed windows process. Otherwise, the exit code of
a cygwin process comes from the exitcode field in _pinfo. */
created during new process creation. If the pipe is closed or a zero
is received on the pipe, it is assumed that the cygwin pid has exited.
Otherwise, various "signals" can be sent to the parent to inform the
parent to perform a certain action. */
static DWORD WINAPI
proc_waiter (void *arg)
{
@@ -768,29 +757,41 @@ proc_waiter (void *arg)
return 0;
}
bool
_pinfo::dup_proc_pipe (HANDLE hProcess)
{
bool res = DuplicateHandle (hMainProc, wr_proc_pipe, hProcess, &wr_proc_pipe,
0, FALSE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
if (!res)
sigproc_printf ("DuplicateHandle failed, pid %d, hProcess %p, %E", pid, hProcess);
else
{
wr_proc_pipe_owner = dwProcessId;
sigproc_printf ("closed wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
pid, dwProcessId);
}
return res;
}
/* function to set up the process pipe and kick off proc_waiter */
int
pinfo::wait ()
{
HANDLE out;
/* FIXME: execed processes should be able to wait for pids that were started
by the process which execed them. */
if (!CreatePipe (&rd_proc_pipe, &out, &sec_none_nih, 16))
if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16))
{
system_printf ("Couldn't create pipe tracker for pid %d, %E",
(*this)->pid);
return 0;
}
/* Duplicate the write end of the pipe into the subprocess. Make it inheritable
so that all of the execed children get it. */
if (!DuplicateHandle (hMainProc, out, hProcess, &((*this)->wr_proc_pipe), 0,
TRUE, DUPLICATE_SAME_ACCESS))
if (!(*this)->dup_proc_pipe (hProcess))
{
system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid,
hProcess);
system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
return 0;
}
CloseHandle (out); /* Don't need this end in this proces */
preserve (); /* Preserve the shared memory associated with the pinfo */
@@ -808,26 +809,38 @@ pinfo::wait ()
return 1;
}
void
_pinfo::sync_proc_pipe ()
{
if (wr_proc_pipe && wr_proc_pipe != INVALID_HANDLE_VALUE)
while (wr_proc_pipe_owner != GetCurrentProcessId ())
low_priority_sleep (0);
}
/* function to send a "signal" to the parent when something interesting happens
in the child. */
bool
pinfo::alert_parent (char sig)
_pinfo::alert_parent (char sig)
{
DWORD nb = 0;
/* Send something to our parent. If the parent has gone away,
close the pipe. */
if (myself->wr_proc_pipe == INVALID_HANDLE_VALUE
if (wr_proc_pipe == INVALID_HANDLE_VALUE
|| !myself->wr_proc_pipe)
/* no parent */;
else if (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 = INVALID_HANDLE_VALUE;
CloseHandle (closeit);
sync_proc_pipe ();
if (WriteFile (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 = wr_proc_pipe;
wr_proc_pipe = INVALID_HANDLE_VALUE;
CloseHandle (closeit);
}
}
return (bool) nb;
}