diff options
author | Christopher Faylor <me@cgf.cx> | 2012-03-17 00:20:29 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2012-03-17 00:20:29 +0400 |
commit | 4aeaedf961029e38cd9c97ac1e32ba91406c9e23 (patch) | |
tree | 88371461329ddcd2c9eac8659dd5d2763da82330 /winsup/cygwin/pinfo.cc | |
parent | d3f6480e44081964526de50792c6d28ca2d24580 (diff) |
* fork.cc (lock_signals): Move to sigproc.h.
(lock_pthread): Ditto.
(hold_everything): Ditto.
(frok::parent): Call myself.prefork() just before calling CreateProcess. Call
myself.postfork () on function exit.
* pinfo.cc (pinfo::pending_rd_proc_pipe): Define.
(pinfo::pending_wr_proc_pipe): Ditto.
(_pinfo::dup_proc_pipe): Delete.
(pinfo::wait): Move pipe creation into pinfo::prefork. Set pipe variables from
pending_*.
(_pinfo::sync_proc_pipe): Delete.
(_pinfo::proc_pipe_owner): Ditto.
(pinfo::prefork): Define new function.
(pinfo::postfork): Ditto.
(pinfo::postexec): Ditto.
(_pinfo::alert_parent): Remove obsolete call to sync_proc_pipe.
(_pinfo::dup_proc_pipe): Delete declaration.
(_pinfo::sync_proc_pipe): Ditto.
(pinfo::pending_rd_proc_pipe): Declare.
(pinfo::pending_wr_proc_pipe): Ditto.
(pinfo::prefork): Declare new function.
(pinfo::postfork): Ditto.
(pinfo::postexec): Ditto.
(pinfo::wr_proc_pipe): Define new wrapper function.
* sigproc.h: Include "sync.h". Move locking functions from fork to here.
* spawn.cc (child_info_spawn::worker): Delete now-unneeded requirement to
record orig_wr_proc_pipe. Call hold_everything prior to doing anything. Call
myself.prefork() if spawning. Replace wr_proc_pipe synchronization with call
to myself.postexec(). Call myself.postfork() if not execing.
* sync.h: Replace #ifdef wrapper with "#pragma once".
Diffstat (limited to 'winsup/cygwin/pinfo.cc')
-rw-r--r-- | winsup/cygwin/pinfo.cc | 111 |
1 files changed, 50 insertions, 61 deletions
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index d7e147ae5..c5e646455 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -49,6 +49,9 @@ pinfo_basic myself_initial NO_COPY; pinfo NO_COPY myself (static_cast<_pinfo *> (&myself_initial)); // Avoid myself != NULL checks +HANDLE NO_COPY pinfo::pending_rd_proc_pipe; +HANDLE NO_COPY pinfo::pending_wr_proc_pipe; + bool is_toplevel_proc; /* Setup the pinfo structure for this process. There may already be a @@ -980,66 +983,16 @@ proc_waiter (void *arg) return 0; } -#ifdef DEBUGGING -#define warn_printf api_fatal -#else -#define warn_printf system_printf -#endif -HANDLE -_pinfo::dup_proc_pipe (HANDLE hProcess, const char *func) -{ - DWORD flags = DUPLICATE_SAME_ACCESS; - HANDLE orig_wr_proc_pipe = wr_proc_pipe; - /* Can't set DUPLICATE_CLOSE_SOURCE for exec case because we could be - execing a non-cygwin process and we need to set the exit value before the - parent sees it. */ - if (this != myself || is_toplevel_proc) - flags |= DUPLICATE_CLOSE_SOURCE; - bool res = DuplicateHandle (GetCurrentProcess (), wr_proc_pipe, - hProcess, &wr_proc_pipe, 0, FALSE, flags); - if (res) - { - wr_proc_pipe_owner = dwProcessId; - sigproc_printf ("(%s) duped wr_proc_pipe %p for pid %d(%u)", func, - wr_proc_pipe, pid, dwProcessId); - } - else - { - DWORD duperr = GetLastError (); - DWORD wfsores = WaitForSingleObject (hProcess, 0); - if (wfsores != WAIT_OBJECT_0) - { - warn_printf ("(%s) process synchronization failed for pid %u/%p, " - "wr_proc_pipe %p vs. %p: DuplicateHandle winerr %d, " - "WFSO returned %u, %E", - func, pid, hProcess, wr_proc_pipe, orig_wr_proc_pipe, duperr, - wfsores); - } - wr_proc_pipe = orig_wr_proc_pipe; - } - return orig_wr_proc_pipe; -} - /* function to set up the process pipe and kick off proc_waiter */ bool pinfo::wait () { - /* If rd_proc_pipe != NULL we're in an execed process which already has - grabbed the read end of the pipe from the previous cygwin process running - with this pid. */ - if (!rd_proc_pipe) - { - /* FIXME: execed processes should be able to wait for pids that were started - by the process which execed them. */ - 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 false; - } + rd_proc_pipe = pending_rd_proc_pipe; + pending_rd_proc_pipe = NULL; - (*this)->dup_proc_pipe (hProcess, "pinfo::wait"); - } + wr_proc_pipe () = pending_wr_proc_pipe; + ForceCloseHandle1 (pending_wr_proc_pipe, wr_proc_pipe); + pending_wr_proc_pipe = NULL; preserve (); /* Preserve the shared memory associated with the pinfo */ @@ -1059,11 +1012,48 @@ pinfo::wait () } void -_pinfo::sync_proc_pipe () +pinfo::prefork (bool detached) +{ + if (wr_proc_pipe () && wr_proc_pipe () != INVALID_HANDLE_VALUE + && !SetHandleInformation (wr_proc_pipe (), HANDLE_FLAG_INHERIT, 0)) + api_fatal ("couldn't set process pipe(%p) inherit state, %E", wr_proc_pipe ()); + /* If rd_proc_pipe != NULL we're in an execed process which already has + grabbed the read end of the pipe from the previous cygwin process running + with this pid. */ + if (!detached) + { + if (!CreatePipe (&pending_rd_proc_pipe, &pending_wr_proc_pipe, + &sec_none_nih, 16)) + api_fatal ("Couldn't create pipe tracker for pid %d, %E", (*this)->pid); + + if (!SetHandleInformation (pending_wr_proc_pipe, HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT)) + api_fatal ("prefork: couldn't set process pipe(%p) inherit state, %E", + pending_wr_proc_pipe); + ProtectHandle1 (pending_rd_proc_pipe, rd_proc_pipe); + ProtectHandle1 (pending_wr_proc_pipe, wr_proc_pipe); + } +} + +void +pinfo::postfork () +{ + if (wr_proc_pipe () && wr_proc_pipe () != INVALID_HANDLE_VALUE + && !SetHandleInformation (wr_proc_pipe (), HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT)) + api_fatal ("postfork: couldn't set process pipe(%p) inherit state, %E", wr_proc_pipe ()); + if (pending_rd_proc_pipe) + ForceCloseHandle1 (pending_rd_proc_pipe, rd_proc_pipe); + if (pending_wr_proc_pipe) + ForceCloseHandle1 (pending_wr_proc_pipe, wr_proc_pipe); +} + +void +pinfo::postexec () { - if (wr_proc_pipe && wr_proc_pipe != INVALID_HANDLE_VALUE) - while (wr_proc_pipe_owner != GetCurrentProcessId ()) - yield (); + if (wr_proc_pipe () && wr_proc_pipe () != INVALID_HANDLE_VALUE + && !ForceCloseHandle (wr_proc_pipe ())) + api_fatal ("postexec: couldn't close wr_proc_pipe(%p), %E", wr_proc_pipe ()); } /* function to send a "signal" to the parent when something interesting happens @@ -1078,11 +1068,10 @@ _pinfo::alert_parent (char sig) FIXME: Is there a race here if we run this while another thread is attempting to exec()? */ - if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || have_execed) + if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself.wr_proc_pipe () || have_execed) /* no parent */; else { - sync_proc_pipe (); if (WriteFile (wr_proc_pipe, &sig, 1, &nb, NULL)) /* all is well */; else if (GetLastError () != ERROR_BROKEN_PIPE) |