diff options
author | Christopher Faylor <me@cgf.cx> | 2004-12-24 18:31:23 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2004-12-24 18:31:23 +0000 |
commit | e1736c2f135a31a8882199169c2dfc5a99f7ce1b (patch) | |
tree | d8aa6f3b12f911e2ed8d2727ea205a8973e47a69 /winsup/cygwin/pinfo.cc | |
parent | 4697fbcd517791570ecc77c32dd9ebf044c4fa03 (diff) | |
download | cygnal-e1736c2f135a31a8882199169c2dfc5a99f7ce1b.tar.gz cygnal-e1736c2f135a31a8882199169c2dfc5a99f7ce1b.tar.bz2 cygnal-e1736c2f135a31a8882199169c2dfc5a99f7ce1b.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/pinfo.cc')
-rw-r--r-- | winsup/cygwin/pinfo.cc | 103 |
1 files changed, 58 insertions, 45 deletions
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index ec51c8530..69a43808a 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -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; } |