Cygwin: spawn: create and maintain winpid symlinks

- If the execve'ed process is a non-Cygwin process, we have to
  create the matching winpid symlink and remove the old one
  ourselves.

- If we spawn a child, the winpid symlink has to be maintained
  by the child process, otherwise it disappears if the parent
  process exits.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2019-02-02 20:01:41 +01:00
parent d6cf2b781f
commit 3a3934252c
2 changed files with 26 additions and 5 deletions

View File

@ -204,6 +204,7 @@ public:
} }
#endif #endif
HANDLE shared_handle () {return h;} HANDLE shared_handle () {return h;}
HANDLE shared_winpid_handle () {return winpid_hdl;}
void set_acl (); void set_acl ();
friend class _pinfo; friend class _pinfo;
friend class winpids; friend class winpids;

View File

@ -725,6 +725,16 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
myself->dwProcessId = pi.dwProcessId; myself->dwProcessId = pi.dwProcessId;
strace.execing = 1; strace.execing = 1;
myself.hProcess = hExeced = pi.hProcess; myself.hProcess = hExeced = pi.hProcess;
if (!real_path.iscygexec ())
{
/* If the child process is not a Cygwin process, we have to
create a new winpid symlink and drop the old one on
behalf of the child process not being able to do this
by itself. */
HANDLE old_winpid_hdl = myself.shared_winpid_handle ();
myself.create_winpid_symlink ();
NtClose (old_winpid_hdl);
}
real_path.get_wide_win32_path (myself->progname); // FIXME: race? real_path.get_wide_win32_path (myself->progname); // FIXME: race?
sigproc_printf ("new process name %W", myself->progname); sigproc_printf ("new process name %W", myself->progname);
if (!iscygwin ()) if (!iscygwin ())
@ -748,13 +758,23 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
child.hProcess = pi.hProcess; child.hProcess = pi.hProcess;
real_path.get_wide_win32_path (child->progname); real_path.get_wide_win32_path (child->progname);
/* FIXME: This introduces an unreferenced, open handle into the child. /* This introduces an unreferenced, open handle into the child.
The purpose is to keep the pid shared memory open so that all of The purpose is to keep the pid shared memory open so that all
the fields filled out by child.remember do not disappear and so of the fields filled out by child.remember do not disappear
there is not a brief period during which the pid is not available. and so there is not a brief period during which the pid is
However, we should try to find another way to do this eventually. */ not available. */
DuplicateHandle (GetCurrentProcess (), child.shared_handle (), DuplicateHandle (GetCurrentProcess (), child.shared_handle (),
pi.hProcess, NULL, 0, 0, DUPLICATE_SAME_ACCESS); pi.hProcess, NULL, 0, 0, DUPLICATE_SAME_ACCESS);
if (!real_path.iscygexec ())
{
/* If the child process is not a Cygwin process, we have to
create a new winpid symlink and induce it into the child
process as well to keep it over the lifetime of the child. */
child.create_winpid_symlink ();
DuplicateHandle (GetCurrentProcess (),
child.shared_winpid_handle (),
pi.hProcess, NULL, 0, 0, DUPLICATE_SAME_ACCESS);
}
child->start_time = time (NULL); /* Register child's starting time. */ child->start_time = time (NULL); /* Register child's starting time. */
child->nice = myself->nice; child->nice = myself->nice;
postfork (child); postfork (child);