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:
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/DevNotes51
-rw-r--r--winsup/cygwin/cygheap.h1
-rw-r--r--winsup/cygwin/dcrt0.cc11
-rw-r--r--winsup/cygwin/pinfo.cc10
-rw-r--r--winsup/cygwin/release/1.7.155
-rw-r--r--winsup/cygwin/spawn.cc42
7 files changed, 110 insertions, 24 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b962d7f91..0e3056e73 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,17 @@
+2012-05-07 Christopher Faylor <me.cygwin2012@cgf.cx>
+
+ * DevNotes: Add entry cgf-000003.
+ * cygheap.h (init_cygheap::pid_handle): Delete.
+ * dcrt0.cc (child_info_spawn::handle_spawn): Keep parent open if we
+ have execed.
+ * pinfo.cc (pinfo::thisproc): Remove pid_handle manipulations.
+ (pinfo::init): Don't consider a reaped process to be available.
+ * spawn.cc (child_info_spawn::worker): Remove pid_handle manipulations.
+ Make wr_proc_pipe and parent noninheritable when starting a program
+ which doesn't use the Cygwin DLL. Conditionally reset wr_proc_pipe to
+ inheritable if CreateProcess fails. Inject wr_proc_pipe handle into
+ non-Cygwin process. Consider a non-cygwin process to be 'synced'.
+
2012-05-03 Christopher Faylor <me.cygwin2012@cgf.cx>
* DevNotes: Add entry cgf-000002.
diff --git a/winsup/cygwin/DevNotes b/winsup/cygwin/DevNotes
index a40161140..59cda286f 100644
--- a/winsup/cygwin/DevNotes
+++ b/winsup/cygwin/DevNotes
@@ -1,3 +1,54 @@
+2012-05-03 cgf-000003
+
+<1.7.15>
+Don't make Cygwin wait for all children of a non-cygwin child program.
+Fixes: http://cygwin.com/ml/cygwin/2012-05/msg00063.html,
+ http://cygwin.com/ml/cygwin/2012-05/msg00075.html
+</1.7.15>
+
+This problem is due to a recent change which added some robustness and
+speed to Cygwin's exec/spawn handling by not trying to force inheritance
+every time a process is started. See ChangeLog entries starting on
+2012-03-20, and multiple on 2012-03-21.
+
+Making the handle inheritable meant that, as usual, there were problems
+with non-Cygwin processes. When Cygwin "execs" a non-Cygwin process N,
+all of its N + 1, N + 2, ... children will also inherit the handle.
+That means that Cygwin will wait until all subprocesses have exited
+before it returns.
+
+I was willing to make this a restriction of starting non-Cygwin
+processes but the problem with allowing that is that it can cause the
+creation of a "limbo" pid when N exits and N + 1 and friends are still
+around. In this scenario, Cygwin dutifully notices that process N has
+died and sets the exit code to indicate that but N's parent will wait on
+rd_proc_pipe and will only return when every N + ... windows process
+has exited.
+
+The removal of cygheap::pid_handle was not related to the initial
+problem that I set out to fix. The change came from the realization
+that we were duping the current process handle into the child twice and
+only needed to do it once. The current process handle is used by exec
+to keep the Windows pid "alive" so that it will not be reused. So, now
+we just close parent in child_info_spawn::handle_spawn iff we're not
+execing.
+
+In debugging this it bothered me that 'ps' identified a nonactive pid as
+active. Part of the reason for this was the 'parent' handle in
+child_info was opened in non-Cygwin processes, keeping the pid alive.
+That has been kluged around (more changes after 1.7.15) but that didn't
+fix the problem. On further investigation, this seems to be caused by
+the fact that the shared memory region pid handles were still being
+passed to non-cygwin children, keeping the pid alive in a limbo-like
+fashion. This was easily fixed by having pinfo::init() consider a
+memory region with PID_REAPED as not available.
+
+This fixed the problem where a pid showed up in the list after a user
+does something like: "bash$ cmd /c start notepad" but, for some reason,
+it does not fix the problem where "bash$ setsid cmd /c start notepad".
+That bears investigation after 1.7.15 is released but it is not a
+regression and so is not a blocker for the release.
+
2012-05-03 cgf-000002
<1.7.15>
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 154ad6a84..4895019aa 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -390,7 +390,6 @@ struct init_cygheap: public mini_cygheap
struct _cygtls **threadlist;
size_t sthreads;
pid_t pid; /* my pid */
- HANDLE pid_handle; /* handle for my pid */
struct { /* Equivalent to using LIST_HEAD. */
struct inode_t *lh_first;
} inode_list; /* Global inode pointer for adv. locking. */
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 63eaa70dd..aea2a564b 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -665,10 +665,15 @@ child_info_spawn::handle_spawn ()
ready (true);
- /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
+ /* Keep pointer to parent open if we've execed so that pid will not be reused.
+ Otherwise, we no longer need this handle so close it.
+ Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
handles might get confused. */
- CloseHandle (child_proc_info->parent);
- child_proc_info->parent = NULL;
+ if (type != _CH_EXEC)
+ {
+ CloseHandle (child_proc_info->parent);
+ child_proc_info->parent = NULL;
+ }
signal_fixup_after_exec ();
fixup_lockf_after_exec ();
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index a13100cfc..daed1cc7b 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -77,11 +77,6 @@ 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.
@@ -305,8 +300,9 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
bool created = shloc != SH_JUSTOPEN;
- if ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
- && cygwin_pid (procinfo->dwProcessId) != procinfo->pid)
+ if ((procinfo->process_state & PID_REAPED)
+ || ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
+ && cygwin_pid (procinfo->dwProcessId) != procinfo->pid))
{
set_errno (ESRCH);
break;
diff --git a/winsup/cygwin/release/1.7.15 b/winsup/cygwin/release/1.7.15
index 43eb9b56b..4e9e64090 100644
--- a/winsup/cygwin/release/1.7.15
+++ b/winsup/cygwin/release/1.7.15
@@ -22,3 +22,8 @@ Bug fixes:
- Avoid "WARNING: Couldn't compute FAST_CWD pointer." message on
Windows 8 Customer Preview 32 bit.
Fixes: http://cygwin.com/ml/cygwin/2012-04/msg00616.html
+
+- Don't make Cygwin wait for all children of a non-cygwin child program.
+ Fixes: http://cygwin.com/ml/cygwin/2012-05/msg00063.html,
+ http://cygwin.com/ml/cygwin/2012-05/msg00075.html
+
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index d296597d1..8b5e382c5 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -517,17 +517,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
myself->sendsig = NULL;
reset_sendsig = true;
}
- /* Save a copy of a handle to the current process around the first time we
- exec so that the pid will not be reused. Why did I stop cygwin from
- generating its own pids again? */
- if (::cygheap->pid_handle)
- /* already done previously */;
- else if (DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
- GetCurrentProcess (), &::cygheap->pid_handle,
- PROCESS_QUERY_INFORMATION, TRUE, 0))
- ProtectHandleINH (::cygheap->pid_handle);
- else
- system_printf ("duplicate to pid_handle failed, %E");
}
if (null_app_name)
@@ -613,6 +602,19 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
else
wr_proc_pipe = my_wr_proc_pipe;
+ /* Don't allow child to inherit these handles if it's not a Cygwin program.
+ wr_proc_pipe will be injected later. parent won't be used by the child
+ so there is no reason for the child to have it open as it can confuse
+ ps into thinking that children of windows processes are all part of
+ the same "execed" process.
+ FIXME: Someday, make it so that parent is never created when starting
+ non-Cygwin processes. */
+ if (!iscygwin ())
+ {
+ SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation (parent, HANDLE_FLAG_INHERIT, 0);
+ }
+
/* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different
effective vs. real ids.
@@ -734,6 +736,12 @@ loop:
myself->exec_sendsig = NULL;
}
myself->process_state &= ~PID_NOTCYGWIN;
+ /* Reset handle inheritance to default when the execution of a non-Cygwin
+ process fails. Only need to do this for _P_OVERLAY since the handle will
+ be closed otherwise. Don't need to do this for 'parent' since it will
+ be closed in every case. See FIXME above. */
+ if (!real_path.iscygexec () && mode == _P_OVERLAY)
+ SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
if (wr_proc_pipe == my_wr_proc_pipe)
wr_proc_pipe = NULL; /* We still own it: don't nuke in destructor */
res = -1;
@@ -755,7 +763,7 @@ loop:
cygpid = myself->pid;
/* We print the original program name here so the user can see that too. */
- syscall_printf ("%d = child_info_spawn::worker(%s, %.9500s)",
+ syscall_printf ("pid %d, prog_arg %s, cmd line %.9500s)",
rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf);
/* Name the handle similarly to proc_subproc. */
@@ -815,6 +823,12 @@ loop:
/* Start the child running */
if (c_flags & CREATE_SUSPENDED)
{
+ /* Inject a non-inheritable wr_proc_pipe handle into child so that we
+ can accurately track when the child exits without keeping this
+ process waiting around for it to exit. */
+ if (!iscygwin ())
+ DuplicateHandle (GetCurrentProcess (), wr_proc_pipe, pi.hProcess, NULL,
+ 0, false, DUPLICATE_SAME_ACCESS);
ResumeThread (pi.hThread);
if (iscygwin ())
strace.write_childpid (pi.dwProcessId);
@@ -827,7 +841,9 @@ loop:
if ((mode == _P_DETACH || mode == _P_NOWAIT) && !iscygwin ())
synced = false;
else
- synced = sync (pi.dwProcessId, pi.hProcess, INFINITE);
+ /* Just mark a non-cygwin process as 'synced'. We will still eventually
+ wait for it to exit in maybe_set_exit_code_from_windows(). */
+ synced = iscygwin () ? sync (pi.dwProcessId, pi.hProcess, INFINITE) : true;
switch (mode)
{