diff options
-rw-r--r-- | winsup/cygwin/local_includes/child_info.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/sigproc.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/spawn.cc | 19 |
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, |