Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2011-11-14 05:29:49 +0400
committerChristopher Faylor <me@cgf.cx>2011-11-14 05:29:49 +0400
commit56a197152621abcdd3d08b0f62daf5b734422860 (patch)
tree7a299853407aa265de302e498de8c31bb93742a5 /winsup/cygwin/pinfo.cc
parent46e7439b9dbed64e4d3388baf425486571593dec (diff)
Throughout use "have_execed" macro rather than "hExeced" global handle.
Throughout rename _PROC_* to _CH_*. * child_info.h: Include "pinfo.h". (child_info_types): Rename _PROC_* -> _CH_* to avoid confusion with similarly named constants. (_PROC_*): Delete unneeded aliases. (PROC_*): Ditto. (CURR_CHILD_INFO_MAGIC): Ditto. (cchildren): Define using "pinfo_minimal". (child_info::set_saw_ctrl_c): Move to (child_info_spawn::set_saw_ctrl_c): Here. (child_info_spawn::lock): New field. (child_info_spawn::hExeced): Ditto. (child_info_spawn::ev): Ditto. (child_info_spawn::~child_info_spawn): Move to sigproc.cc. (child_info_spawn::child_info_spawn): Ditto. (child_info_spawn::cleanup): Declare new function. (child_info_spawn::set_saw_ctrl_c): Move to this class. Set flag only when execed and return true when we have set the flag. (child_info_spawn::child_info_spawn::signal_myself_exited): New function. (child_info_spawn::wait_for_myself): Ditto. (child_info_spawn::has_execed_cygwin): Ditto. (child_info_spawn::has_execed): Ditto. Replaces "hExeced" test. (child_info_spawn::operator HANDLE&): New operator. (child_info_spawn::worker): Define old "spawn_guts" as class member. (ch_spawn): Declare. (have_execed): Define. (have_execed_cygwin): Ditto. * cygheap.h: Update comment. * dcrt0.cc (get_cygwin_startup_info): Use _CH_* enums. (child_info_spawn::handle_spawn): Ditto. (dll_crt0_0): Ditto. (multiple_cygwin_problem): Ditto. * exceptions.cc (chExeced): Delete obsolete declaration. (ctrl_c_handler): Reference set_saw_ctrl_c via new ch_spawn global. * globals.cc (hExeced): Delete. * pinfo.cc (pinfo::thisproc): Refer to cygheap as ::cygheap for consistency in handle naming when -DDEBUGGING. (pinfo::init): Accommodate case where myself.h is known but h0 is passed in. (pinfo::pinfo): New constructor for setting up a pinfo passed in by previous exec'or. (pinfo::proc_waiter): Don't handle subprocess if we're in the process of exiting due to an exec of a cygwin process. Don't close rd_proc_pipe here. Close it when we actually are finished with the process. Use new ch_spawn.signal_myself_exited function to let exec stub know that subprocess has exited. (pinfo::wait): Clarify debugging output. (pinfo::release): Use "close_h" to close all handles to avoid races. (winpids::add): Assume that elements of the array do not need to be zeroed and are properly initialized or suffer problems on pinfo::release. Don't close hProcess since release does that now. * pinfo.h: Update comment. (pinfo_minimal): Move some elements from pinfo here so that child_info_spawn can use them. (pinfo): Inherit from pinfo_minimal. (pinfo::pinfo): Modify to accommodate new pinfo_minimal. (pinfo::allow_remove): New function. * sigproc.cc (proc_subproc): Use boolean values for true/false. Implement PROC_EXEC_CLEANUP. (proc_terminate): Set ppid = 1 since the procs list will only be iterated when the process has not execed. Don't do any cleanup here since it is now handled in pinfo::release. (sigproc_init): Initialize sync_proc_subproc earlier. (child_info::child_info): Assume that all important fields are properly initialized and avoid memset(). (child_info_spawn::child_info_spawn): Specifically test for execing and then set up appropriate fields in the struct. (child_info_spawn::cleanup): Define new function. (child_info_spawn::record_children): Specifically test for being execed here. Fill in pinfo_minimal part of children array. (child_info_spawn::reattach_children): Use constructor to duplicate information for previous exec'or. Add more debugging output. (remove_proc): Force deletion of thread when exiting due to exec. Rely on pinfo::cleanup in release. * sigproc.h (PROC_EXEC_CLEANUP): New enum. (PROC_DETACHED_CHILD): Delete. * spawn.cc (chExeced): Delete. (child_info_spawn::worker): Rename from spawn_guts. Use elements of child_info_spawn throughout rather than ch.whatever. Use ::cygheap to refer to global rather than element of child_info. Use wait_for_myself() rather than waitpid(). Call child_info_spawn::cleanup on function return. (spawnve): Reflect movement of spawn_guts functionality into child_info_spawn::worker. * syscalls.cc (popen): Ditto. * winsup.h (spawn_guts): Delete declaration.
Diffstat (limited to 'winsup/cygwin/pinfo.cc')
-rw-r--r--winsup/cygwin/pinfo.cc115
1 files changed, 77 insertions, 38 deletions
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index ea30293ba..52aac9349 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -77,10 +77,10 @@ pinfo::thisproc (HANDLE h)
else if (!child_proc_info) /* child_proc_info is only set when this process
was started by another cygwin process */
procinfo->start_time = time (NULL); /* Register our starting time. */
- else if (cygheap->pid_handle)
+ else if (::cygheap->pid_handle)
{
- ForceCloseHandle (cygheap->pid_handle);
- cygheap->pid_handle = NULL;
+ ForceCloseHandle (::cygheap->pid_handle);
+ ::cygheap->pid_handle = NULL;
}
}
@@ -215,6 +215,24 @@ pinfo::exit (DWORD n)
}
# undef self
+inline void
+pinfo::_pinfo_release ()
+{
+ if (procinfo)
+ {
+ void *unmap_procinfo = procinfo;
+ procinfo = NULL;
+ UnmapViewOfFile (unmap_procinfo);
+ }
+ HANDLE close_h;
+ if (h)
+ {
+ close_h = h;
+ h = NULL;
+ ForceCloseHandle1 (close_h, pinfo_shared_handle);
+ }
+}
+
void
pinfo::init (pid_t n, DWORD flag, HANDLE h0)
{
@@ -233,7 +251,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
DWORD access = FILE_MAP_READ
| (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW)
? FILE_MAP_WRITE : 0);
- if (!h0)
+ if (!h0 || myself.h)
shloc = (flag & (PID_IN_USE | PID_EXECED)) ? SH_JUSTCREATE : SH_JUSTOPEN;
else
{
@@ -331,7 +349,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
break;
loop:
- release ();
+ _pinfo_release ();
if (h0)
yield ();
}
@@ -344,7 +362,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
else
{
h = h0;
- release ();
+ _pinfo_release ();
}
}
@@ -365,6 +383,35 @@ pinfo::set_acl()
debug_printf ("NtSetSecurityObject %p", status);
}
+pinfo::pinfo (HANDLE parent, pinfo_minimal& from, pid_t pid):
+ pinfo_minimal (), destroy (false), procinfo (NULL), waiter_ready (false),
+ wait_thread (NULL)
+{
+ HANDLE herr;
+ const char *duperr = NULL;
+ if (!DuplicateHandle (parent, herr = from.rd_proc_pipe, GetCurrentProcess (),
+ &rd_proc_pipe, 0, false, DUPLICATE_SAME_ACCESS))
+ duperr = "couldn't duplicate parent rd_proc_pipe handle %p for forked child %d after exec, %E";
+ else if (!DuplicateHandle (parent, herr = from.hProcess, GetCurrentProcess (),
+ &hProcess, 0, false, DUPLICATE_SAME_ACCESS))
+ duperr = "couldn't duplicate parent process handle %p for forked child %d after exec, %E";
+ else
+ {
+ h = NULL;
+ DuplicateHandle (parent, from.h, GetCurrentProcess (), &h, 0, false,
+ DUPLICATE_SAME_ACCESS);
+ init (pid, PID_MAP_RW, h);
+ if (*this)
+ return;
+ }
+
+ if (duperr)
+ debug_printf (duperr, herr, pid);
+
+ /* Returning with procinfo == NULL. Any open handles will be closed by the
+ destructor. */
+}
+
const char *
_pinfo::_ctty (char *buf)
{
@@ -868,6 +915,7 @@ proc_waiter (void *arg)
si.si_stime = pchildren[rc].rusage_self.ru_stime;
#endif
pid_t pid = vchild->pid;
+ bool its_me = vchild == myself;
for (;;)
{
@@ -881,6 +929,9 @@ proc_waiter (void *arg)
break;
}
+ if (!its_me && have_execed_cygwin)
+ break;
+
si.si_uid = vchild->uid;
switch (buf)
@@ -889,8 +940,6 @@ proc_waiter (void *arg)
continue;
case 0:
/* Child exited. Do some cleanup and signal myself. */
- CloseHandle (vchild.rd_proc_pipe);
- vchild.rd_proc_pipe = NULL;
vchild.maybe_set_exit_code_from_windows ();
if (WIFEXITED (vchild->exitcode))
si.si_code = CLD_EXITED;
@@ -918,15 +967,8 @@ proc_waiter (void *arg)
continue;
}
- /* Special case: If the "child process" that died is us, then we're
- execing. Just call proc_subproc directly and then exit this loop.
- We're done here. */
- if (hExeced)
- {
- /* execing. no signals available now. */
- proc_subproc (PROC_CLEARWAIT, 0);
- break;
- }
+ if (its_me && ch_spawn.signal_myself_exited ())
+ break;
/* Send a SIGCHLD to myself. We do this here, rather than in proc_subproc
to avoid the proc_subproc lock since the signal thread will eventually
@@ -1003,13 +1045,13 @@ pinfo::wait ()
waiter_ready = false;
/* Fire up a new thread to track the subprocess */
- cygthread *h = new cygthread (proc_waiter, this, "proc_waiter");
+ cygthread *h = new cygthread (proc_waiter, this, "waitproc");
if (!h)
sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid);
else
{
wait_thread = h;
- sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_pipe %p",
+ sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_proc_pipe %p",
(*this)->pid, (*this)->dwProcessId, rd_proc_pipe);
}
@@ -1036,7 +1078,7 @@ _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 || hExeced)
+ if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || have_execed)
/* no parent */;
else
{
@@ -1059,17 +1101,19 @@ _pinfo::alert_parent (char sig)
void
pinfo::release ()
{
- if (procinfo)
+ _pinfo_release ();
+ HANDLE close_h;
+ if (rd_proc_pipe)
{
- void *unmap_procinfo = procinfo;
- procinfo = NULL;
- UnmapViewOfFile (unmap_procinfo);
+ close_h = rd_proc_pipe;
+ rd_proc_pipe = NULL;
+ ForceCloseHandle1 (close_h, rd_proc_pipe);
}
- if (h)
+ if (hProcess)
{
- HANDLE close_h = h;
- h = NULL;
- ForceCloseHandle1 (close_h, pinfo_shared_handle);
+ close_h = hProcess;
+ hProcess = NULL;
+ ForceCloseHandle1 (close_h, childhProc);
}
}
@@ -1145,15 +1189,15 @@ winpids::add (DWORD& nelem, bool winpid, DWORD pid)
}
pinfo& p = pinfolist[nelem];
+ memset (&p, 0, sizeof (p));
- /* Open a the process to prevent a subsequent exit from invalidating the
+ /* Open a process to prevent a subsequent exit from invalidating the
shared memory region. */
p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, pid);
_onreturn onreturn (p.hProcess);
/* If we couldn't open the process then we don't have rights to it and should
- make a copy of the shared memory area if it exists (it may not).
- */
+ make a copy of the shared memory area if it exists (it may not). */
bool perform_copy;
if (!p.hProcess)
perform_copy = true;
@@ -1226,8 +1270,7 @@ out:
else
{
*pnew = *p.procinfo;
- if ((_pinfo *) p != (_pinfo *) myself)
- p.release ();
+ p.release ();
p.procinfo = pnew;
p.destroy = false;
}
@@ -1344,11 +1387,7 @@ winpids::release ()
if (pinfolist[i] == (_pinfo *) myself)
continue;
else if (pinfolist[i].hProcess)
- {
- if (pinfolist[i])
- pinfolist[i].release ();
- CloseHandle (pinfolist[i].hProcess);
- }
+ pinfolist[i].release ();
else if ((p = pinfolist[i]))
{
pinfolist[i].procinfo = NULL;