aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/spawn.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/spawn.cc')
-rw-r--r--winsup/cygwin/spawn.cc32
1 files changed, 20 insertions, 12 deletions
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index ef175e7..680f0fe 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -542,10 +542,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->ctty ? ::cygheap->ctty->tc_getpgid () : 0;
if (!iscygwin () && ctty_pgid && ctty_pgid != myself->pgid)
c_flags |= CREATE_NEW_PROCESS_GROUP;
- refresh_cygheap ();
-
- if (c_flags & CREATE_NEW_PROCESS_GROUP)
- InterlockedOr ((LONG *) &myself->process_state, PID_NEW_PG);
if (mode == _P_DETACH)
/* all set */;
@@ -605,10 +601,17 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->user.deimpersonate ();
if (!real_path.iscygexec () && mode == _P_OVERLAY)
- InterlockedOr ((LONG *) &myself->process_state, PID_NOTCYGWIN);
+ {
+ LONG pidflags = PID_NOTCYGWIN;
+ if (c_flags & CREATE_NEW_PROCESS_GROUP)
+ pidflags |= PID_NEW_PG;
+ InterlockedOr ((LONG *) &myself->process_state, pidflags);
+ }
cygpid = (mode != _P_OVERLAY) ? create_cygwin_pid () : myself->pid;
+ cygheap->lock ();
+ refresh_cygheap ();
wchar_t wcmd[(size_t) cmd];
if (!::cygheap->user.issetuid ()
|| (::cygheap->user.saved_uid == ::cygheap->user.real_uid
@@ -707,7 +710,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
myself->sendsig = myself->exec_sendsig;
myself->exec_sendsig = NULL;
}
- InterlockedAnd ((LONG *) &myself->process_state, ~PID_NOTCYGWIN);
+ InterlockedAnd ((LONG *) &myself->process_state,
+ ~(PID_NOTCYGWIN|PID_NEW_PG));
/* 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
@@ -725,6 +729,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->user.reimpersonate ();
res = -1;
+ cygheap->unlock ();
__leave;
}
@@ -761,21 +766,22 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
NtClose (old_winpid_hdl);
real_path.get_wide_win32_path (myself->progname); // FIXME: race?
sigproc_printf ("new process name %W", myself->progname);
- if (!iscygwin ())
- close_all_files ();
}
else
{
myself->set_has_pgid_children ();
ProtectHandle (pi.hThread);
pinfo child (cygpid,
- PID_IN_USE | (real_path.iscygexec () ? 0 : PID_NOTCYGWIN));
+ PID_IN_USE |
+ (real_path.iscygexec () ? 0 : PID_NOTCYGWIN) |
+ ((c_flags & CREATE_NEW_PROCESS_GROUP) ? PID_NEW_PG : 0));
if (!child)
{
syscall_printf ("pinfo failed");
if (get_errno () != ENOMEM)
set_errno (EAGAIN);
res = -1;
+ cygheap->unlock ();
__leave;
}
child->dwProcessId = pi.dwProcessId;
@@ -811,6 +817,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
CloseHandle (pi.hProcess);
ForceCloseHandle (pi.hThread);
res = -1;
+ cygheap->unlock ();
__leave;
}
}
@@ -839,6 +846,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
/* 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;
+ cygheap->unlock ();
switch (mode)
{
@@ -855,8 +863,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
}
else
{
- if (iscygwin ())
- close_all_files (true);
+ close_all_files (iscygwin ());
if (!my_wr_proc_pipe
&& WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
wait_for_myself ();
@@ -943,6 +950,7 @@ spawnve (int mode, const char *path, const char *const *argv,
if (!envp)
envp = empty_env;
+ child_info_spawn ch_spawn_local (_CH_NADA, false);
switch (_P_MODE (mode))
{
case _P_OVERLAY:
@@ -956,7 +964,7 @@ spawnve (int mode, const char *path, const char *const *argv,
case _P_WAIT:
case _P_DETACH:
case _P_SYSTEM:
- ret = ch_spawn.worker (path, argv, envp, mode);
+ ret = ch_spawn_local.worker (path, argv, envp, mode);
break;
default:
set_errno (EINVAL);