aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/local_includes/child_info.h3
-rw-r--r--winsup/cygwin/sigproc.cc2
-rw-r--r--winsup/cygwin/spawn.cc19
3 files changed, 19 insertions, 5 deletions
diff --git a/winsup/cygwin/local_includes/child_info.h b/winsup/cygwin/local_includes/child_info.h
index bce5ca7..91d5433 100644
--- a/winsup/cygwin/local_includes/child_info.h
+++ b/winsup/cygwin/local_includes/child_info.h
@@ -142,11 +142,12 @@ struct spawn_worker_args
const char *const *envp;
int stdfds[3];
int cwdfd;
+ pid_t pgid;
sigset_t *sigmask;
spawn_worker_args (const char *const *argv, const char *const envp[])
: argv (argv), envp (envp), stdfds {-1, -1, -1}, cwdfd (AT_FDCWD),
- sigmask (NULL)
+ pgid (-1), sigmask (NULL)
{ }
};
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 3618879..7020071 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -257,7 +257,7 @@ proc_subproc (DWORD what, uintptr_t val)
{
vchild->uid = myself->uid;
vchild->gid = myself->gid;
- vchild->pgid = myself->pgid;
+ InterlockedCompareExchange ((LONG*) &vchild->pgid, myself->pgid, 0);
vchild->sid = myself->sid;
vchild->ctty = myself->ctty;
vchild->cygstarted = true;
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 4c17ee6..e17ef10 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -613,7 +613,8 @@ child_info_spawn::worker (int mode, const char *prog_arg,
they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */
pid_t ctty_pgid =
::cygheap->ctty ? ::cygheap->ctty->tc_getpgid () : 0;
- if (!iscygwin () && ctty_pgid && ctty_pgid != myself->pgid)
+ if (!iscygwin () && ctty_pgid &&
+ ctty_pgid != (args.pgid == -1 ? myself->pgid : args.pgid))
c_flags |= CREATE_NEW_PROCESS_GROUP;
if (mode == _P_DETACH)
@@ -859,6 +860,8 @@ child_info_spawn::worker (int mode, const char *prog_arg,
}
child->dwProcessId = pi.dwProcessId;
child.hProcess = pi.hProcess;
+ if (args.pgid != -1)
+ child->pgid = args.pgid ?: cygpid;
real_path.get_wide_win32_path (child->progname);
/* This introduces an unreferenced, open handle into the child.
@@ -1470,17 +1473,27 @@ do_posix_spawn (pid_t *pid, const char *path,
/* TODO: possibly implement spawnattr flags:
POSIX_SPAWN_RESETIDS
- POSIX_SPAWN_SETPGROUP
POSIX_SPAWN_SETSCHEDPARAM
POSIX_SPAWN_SETSCHEDULER */
if (sa)
{
- if ((*sa)->sa_flags & ~(POSIX_SPAWN_SETSIGMASK|POSIX_SPAWN_SETSIGDEF))
+ static const short FASTPATH_FLAGS =
+ POSIX_SPAWN_SETSIGMASK|POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETPGROUP;
+ if ((*sa)->sa_flags & ~FASTPATH_FLAGS)
goto fallback;
if ((*sa)->sa_flags & POSIX_SPAWN_SETSIGMASK)
args.sigmask = &(*sa)->sa_sigmask;
+ if ((*sa)->sa_flags & POSIX_SPAWN_SETPGROUP)
+ {
+ args.pgid = (*sa)->sa_pgroup;
+ if (args.pgid < 0)
+ return EINVAL;
+ /* According to POSIX there should be more error cases, but setpgid
+ does not implement them, so replicate its behavior. */
+ }
+
if ((*sa)->sa_flags & POSIX_SPAWN_SETSIGDEF)
{
sigs = (struct sigaction *) cmalloc (HEAP_SIGS,