From bd9faa81bff04df273d7b158a27cfe9765cacca4 Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Thu, 27 Jan 2022 22:58:01 -0800 Subject: [PATCH] libast: Use POSIX_SPAWN_SETSID in spawnveg when needed (#439) This commit implements support for POSIX_SPAWN_SETSID in spawnveg(3). The fork/vfork fallback for spawnveg already attempts to use setsid in the manner described by the man page, so the posix_spawn implementation should also do so. src/lib/libast/comp/spawnveg.c: - Add support for POSIX_SPAWN_SETSID to the posix_spawn version of spawnveg. - Minor extra: Remove dead code that's never used (the _lib_posix_spawn < 2 code block is inside of _lib_posix_spawn > 1, plus when it's manually enabled by changing the previous #if condition you'll find it causes many regression test failures (at least on OpenBSD)). src/lib/libast/man/spawnveg.3: - Document that spawnveg cannot make the new process a session leader if the operating system doesn't support POSIX_SPAWN_SETSID and the new process was created using posix_spawn. --- src/lib/libast/comp/spawnveg.c | 22 ++++++++++------------ src/lib/libast/man/spawnveg.3 | 11 +++++++++-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/lib/libast/comp/spawnveg.c b/src/lib/libast/comp/spawnveg.c index bb0db2a8a..ee78d9960 100644 --- a/src/lib/libast/comp/spawnveg.c +++ b/src/lib/libast/comp/spawnveg.c @@ -47,20 +47,27 @@ NoN(spawnveg) pid_t spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) { - int err; + int err, flags = 0; pid_t pid; posix_spawnattr_t attr; if (err = posix_spawnattr_init(&attr)) goto nope; +#if POSIX_SPAWN_SETSID + if (pgid == -1) + flags |= POSIX_SPAWN_SETSID; + else +#endif if (pgid) + flags |= POSIX_SPAWN_SETPGROUP; + if (flags && (err = posix_spawnattr_setflags(&attr, flags))) + goto bad; + if (pgid && pgid != -1) { if (pgid <= 1) pgid = 0; if (err = posix_spawnattr_setpgroup(&attr, pgid)) goto bad; - if (err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP)) - goto bad; } if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ)) { @@ -68,15 +75,6 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) goto bad; } posix_spawnattr_destroy(&attr); -#if _lib_posix_spawn < 2 - if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) == 127) - { - while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); - if (!access(path, X_OK)) - errno = ENOEXEC; - pid = -1; - } -#endif return pid; bad: posix_spawnattr_destroy(&attr); diff --git a/src/lib/libast/man/spawnveg.3 b/src/lib/libast/man/spawnveg.3 index 4df6d0620..960614b82 100644 --- a/src/lib/libast/man/spawnveg.3 +++ b/src/lib/libast/man/spawnveg.3 @@ -68,7 +68,7 @@ are as in .L pgid controls the new process group and session: .TP -.L <0 +.L -1 The new process becomes a session leader. It is called in the child context. .TP @@ -86,5 +86,12 @@ The .L spawnveg function cannot set the terminal process group. As a result, it is incompatible with job control when used with terminals. +Additionally, if the +.L POSIX_SPAWN_SETSID +attribute is not supported, then +.L spawnveg +cannot make the new process a session leader when using the +.I posix_spawn +API. .SH "SEE ALSO" -fork(2), exec(2), setpgid(2), setsid(2), spawnve(2) +fork(2), posix_spawn(3), exec(2), setpgid(2), setsid(2), spawnve(2)