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:
Diffstat (limited to 'winsup/cygwin/pinfo.cc')
-rw-r--r--winsup/cygwin/pinfo.cc97
1 files changed, 81 insertions, 16 deletions
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index eb4923e9b..2615e32ac 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -49,6 +49,8 @@ pinfo_basic myself_initial NO_COPY;
pinfo NO_COPY myself (static_cast<_pinfo *> (&myself_initial)); // Avoid myself != NULL checks
+bool is_toplevel_proc;
+
/* Setup the pinfo structure for this process. There may already be a
_pinfo for this "pid" if h != NULL. */
@@ -77,6 +79,11 @@ 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)
+ {
+ ForceCloseHandle (::cygheap->pid_handle);
+ ::cygheap->pid_handle = NULL;
+ }
}
/* Initialize the process table entry for the current task.
@@ -107,13 +114,13 @@ pinfo_init (char **envp, int envc)
myself->process_state |= PID_ACTIVE;
myself->process_state &= ~(PID_INITIALIZING | PID_EXITED | PID_REAPED);
- myself.preserve ();
debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
}
static DWORD
status_exit (DWORD x)
{
+ const char *find_first_notloaded_dll (path_conv &);
switch (x)
{
case STATUS_DLL_NOT_FOUND:
@@ -299,16 +306,8 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
bool created = shloc != SH_JUSTOPEN;
- if (!created && createit && (procinfo->process_state & PID_REAPED))
- {
- memset (procinfo, 0, sizeof (*procinfo));
- created = true; /* Lie that we created this - just reuse old
- shared memory */
- }
-
- if ((procinfo->process_state & PID_REAPED)
- || ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
- && cygwin_pid (procinfo->dwProcessId) != procinfo->pid))
+ if ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
+ && cygwin_pid (procinfo->dwProcessId) != procinfo->pid)
{
set_errno (ESRCH);
break;
@@ -655,6 +654,7 @@ _pinfo::commune_request (__uint32_t code, ...)
HANDLE& hp = si._si_commune._si_process_handle;
HANDLE& fromthem = si._si_commune._si_read_handle;
HANDLE request_sync = NULL;
+ bool locked = false;
res.s = NULL;
res.n = 0;
@@ -681,6 +681,7 @@ _pinfo::commune_request (__uint32_t code, ...)
}
va_end (args);
+ locked = true;
char name_buf[MAX_PATH];
request_sync = CreateSemaphore (&sec_none_nih, 0, LONG_MAX,
shared_name (name_buf, "commune", myself->pid));
@@ -979,10 +980,63 @@ 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)
+{
+ 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 && WaitForSingleObject (hProcess, 0) != WAIT_OBJECT_0)
+ {
+ wr_proc_pipe = orig_wr_proc_pipe;
+ warn_printf ("something failed for pid %d: res %d, hProcess %p, wr_proc_pipe %p vs. %p, %E",
+ res, pid, hProcess, wr_proc_pipe, orig_wr_proc_pipe);
+ }
+ else
+ {
+ wr_proc_pipe_owner = dwProcessId;
+ sigproc_printf ("duped wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
+ pid, dwProcessId);
+ }
+ 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;
+ }
+
+ if (!(*this)->dup_proc_pipe (hProcess))
+ {
+ system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
+ return false;
+ }
+ }
+
preserve (); /* Preserve the shared memory associated with the pinfo */
waiter_ready = false;
@@ -1000,6 +1054,14 @@ pinfo::wait ()
return true;
}
+void
+_pinfo::sync_proc_pipe ()
+{
+ if (wr_proc_pipe && wr_proc_pipe != INVALID_HANDLE_VALUE)
+ while (wr_proc_pipe_owner != GetCurrentProcessId ())
+ yield ();
+}
+
/* function to send a "signal" to the parent when something interesting happens
in the child. */
bool
@@ -1012,18 +1074,21 @@ _pinfo::alert_parent (char sig)
FIXME: Is there a race here if we run this while another thread is attempting
to exec()? */
- if (my_wr_proc_pipe)
+ if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || have_execed)
+ /* no parent */;
+ else
{
- if (WriteFile (my_wr_proc_pipe, &sig, 1, &nb, NULL))
+ 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
{
ppid = 1;
- HANDLE closeit = my_wr_proc_pipe;
- my_wr_proc_pipe = NULL;
- ForceCloseHandle1 (closeit, wr_proc_pipe);
+ HANDLE closeit = wr_proc_pipe;
+ wr_proc_pipe = INVALID_HANDLE_VALUE;
+ CloseHandle (closeit);
}
}
return (bool) nb;