commit 252e2ad869637ca3ef8690854a8fac784b869ec9
parent 8ba811fb48d666a23d60a5ce3a947dcac7baf6ea
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date: Sun, 10 Sep 2023 04:59:41 +0000
Add POSIX_SPAWN_SETSID support to cspawn
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat:
5 files changed, 131 insertions(+), 73 deletions(-)
diff --git a/configure b/configure
@@ -640,10 +640,11 @@ choose cl explicit_bzero 'explicit_bzero()'
choose cl getrandom 'getrandom()'
choose cl grndinsecure 'GRND_INSECURE'
choose cl chroot 'chroot()'
+choose cl posixspawnsetsid 'POSIX_SPAWN_SETSID' ${spawn_lib}
# Here are the evil irreducible run-time sysdeps.
choose clr devurandom '/dev/urandom'
-choose clr posixspawnearlyreturn 'posix_spawn() returning early'
+choose clr posixspawnearlyreturn 'posix_spawn() incorrectly returning early' ${spawn_lib}
# Finally, produce config.mak and config.h
diff --git a/package/deps.mak b/package/deps.mak
@@ -309,7 +309,7 @@ src/libstddjb/child_spawn1_socket.o src/libstddjb/child_spawn1_socket.lo: src/li
src/libstddjb/child_spawn2.o src/libstddjb/child_spawn2.lo: src/libstddjb/child_spawn2.c src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h
src/libstddjb/child_spawn3.o src/libstddjb/child_spawn3.lo: src/libstddjb/child_spawn3.c src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/types.h
src/libstddjb/coe.o src/libstddjb/coe.lo: src/libstddjb/coe.c src/include/skalibs/djbunix.h
-src/libstddjb/cspawn.o src/libstddjb/cspawn.lo: src/libstddjb/cspawn.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/include/skalibs/exec.h src/include/skalibs/selfpipe.h src/include/skalibs/sig.h src/include/skalibs/sysdeps.h
+src/libstddjb/cspawn.o src/libstddjb/cspawn.lo: src/libstddjb/cspawn.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/include/skalibs/exec.h src/include/skalibs/nonposix.h src/include/skalibs/selfpipe.h src/include/skalibs/sig.h src/include/skalibs/sysdeps.h
src/libstddjb/deepsleepuntil.o src/libstddjb/deepsleepuntil.lo: src/libstddjb/deepsleepuntil.c src/include/skalibs/iopause.h src/include/skalibs/tai.h
src/libstddjb/devino_cmp.o src/libstddjb/devino_cmp.lo: src/libstddjb/devino_cmp.c src/include/skalibs/devino.h
src/libstddjb/dir_close.o src/libstddjb/dir_close.lo: src/libstddjb/dir_close.c src/include/skalibs/direntry.h
diff --git a/src/include/skalibs/cspawn.h b/src/include/skalibs/cspawn.h
@@ -8,6 +8,7 @@
#define CSPAWN_FLAGS_SELFPIPE_FINISH 0x0001U
#define CSPAWN_FLAGS_SIGBLOCKNONE 0x0002U
+#define CSPAWN_FLAGS_SETSID 0x0004U
#define CSPAWN_FA_CLOSE 0x0000U
#define CSPAWN_FA_COPY 0x0001U
diff --git a/src/libstddjb/cspawn.c b/src/libstddjb/cspawn.c
@@ -2,10 +2,93 @@
#include <skalibs/sysdeps.h>
+#ifdef SKALIBS_HASPOSIXSPAWN
+#include <skalibs/nonposix.h>
+#endif
+
#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <skalibs/allreadwrite.h>
+#include <skalibs/sig.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/exec.h>
#include <skalibs/cspawn.h>
+static inline void cspawn_child_exec (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
+{
+ for (size_t i = 0 ; i < n ; i++)
+ {
+ switch (fa[i].type)
+ {
+ case CSPAWN_FA_CLOSE : fd_close(fa[i].x.fd) ; break ;
+ case CSPAWN_FA_COPY :
+ if (fd_copy(fa[i].x.fd2[0], fa[i].x.fd2[1]) == -1) return ;
+ break ;
+ case CSPAWN_FA_MOVE :
+ if (fd_move(fa[i].x.fd2[0], fa[i].x.fd2[1]) == -1) return ;
+ break ;
+ case CSPAWN_FA_OPEN :
+ {
+ int fd = open(fa[i].x.openinfo.file, fa[i].x.openinfo.oflag, fa[i].x.openinfo.mode) ;
+ if (fd == -1) return ;
+ if (fd_move(fa[i].x.openinfo.fd, fd) == -1) return ;
+ break ;
+ }
+ default :
+ errno = EINVAL ; return ;
+ }
+ }
+
+ if (flags & CSPAWN_FLAGS_SELFPIPE_FINISH) selfpipe_finish() ;
+ if (flags & CSPAWN_FLAGS_SIGBLOCKNONE) sig_blocknone() ;
+ if (flags & CSPAWN_FLAGS_SETSID) setsid() ;
+
+ exec_ae(prog, argv, envp) ;
+}
+
+static inline pid_t cspawn_fork (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
+{
+ pid_t pid ;
+ int p[2] ;
+ char c ;
+
+ if (pipecoe(p) == -1) return 0 ;
+ pid = fork() ;
+ if (pid == -1)
+ {
+ fd_close(p[1]) ;
+ fd_close(p[0]) ;
+ return 0 ;
+ }
+ if (!pid)
+ {
+ cspawn_child_exec(prog, argv, envp, flags, fa, n) ;
+ c = errno ;
+ fd_write(p[1], &c, 1) ;
+ _exit(127) ;
+ }
+
+ fd_close(p[1]) ;
+ p[1] = fd_read(p[0], &c, 1) ;
+ if (p[1] < 0)
+ {
+ fd_close(p[0]) ;
+ return 0 ;
+ }
+ fd_close(p[0]) ;
+ if (p[1])
+ {
+ wait_pid(pid, &p[0]) ;
+ errno = (unsigned char)c ;
+ return 0 ;
+ }
+ return pid ;
+}
+
#ifdef SKALIBS_HASPOSIXSPAWN
#include <signal.h>
@@ -19,8 +102,6 @@
#include <sys/wait.h>
-#include <skalibs/allreadwrite.h>
-
static inline pid_t cspawn_workaround (pid_t pid, int const *p)
{
siginfo_t si ;
@@ -50,7 +131,7 @@ static inline pid_t cspawn_workaround (pid_t pid, int const *p)
#endif
-pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
+static inline pid_t cspawn_pspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
{
pid_t pid ;
posix_spawnattr_t attr ;
@@ -139,82 +220,27 @@ pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp
return 0 ;
}
-#else
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <skalibs/allreadwrite.h>
-#include <skalibs/sig.h>
-#include <skalibs/selfpipe.h>
-#include <skalibs/exec.h>
+#ifdef SKALIBS_HASPOSIXSPAWNSETSID
-static inline void cspawn_child_exec (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
+pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
{
- for (size_t i = 0 ; i < n ; i++)
- {
- switch (fa[i].type)
- {
- case CSPAWN_FA_CLOSE : fd_close(fa[i].x.fd) ; break ;
- case CSPAWN_FA_COPY :
- if (fd_copy(fa[i].x.fd2[0], fa[i].x.fd2[1]) == -1) return ;
- break ;
- case CSPAWN_FA_MOVE :
- if (fd_move(fa[i].x.fd2[0], fa[i].x.fd2[1]) == -1) return ;
- break ;
- case CSPAWN_FA_OPEN :
- {
- int fd = open(fa[i].x.openinfo.file, fa[i].x.openinfo.oflag, fa[i].x.openinfo.mode) ;
- if (fd == -1) return ;
- if (fd_move(fa[i].x.openinfo.fd, fd) == -1) return ;
- break ;
- }
- default :
- errno = EINVAL ; return ;
- }
- }
-
- if (flags & CSPAWN_FLAGS_SELFPIPE_FINISH) selfpipe_finish() ;
- if (flags & CSPAWN_FLAGS_SIGBLOCKNONE) sig_blocknone() ;
+ return cspawn_pspawn(prog, argv, envp, flags, fa, n) ;
}
+#else
+
pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
{
- pid_t pid ;
- int p[2] ;
- char c ;
+ return flags & CSPAWN_FLAGS_SETSID ? cspawn_fork(prog, argv, envp, flags, fa, n) : cspawn_pspawn(prog, argv, envp, flags, fa, n) ;
+}
- if (pipecoe(p) == -1) return 0 ;
- pid = fork() ;
- if (pid == -1)
- {
- fd_close(p[1]) ;
- fd_close(p[0]) ;
- return 0 ;
- }
- if (!pid)
- {
- cspawn_child_exec(prog, argv, envp, flags, fa, n) ;
- c = errno ;
- fd_write(p[1], &c, 1) ;
- _exit(127) ;
- }
+#endif
- fd_close(p[1]) ;
- p[1] = fd_read(p[0], &c, 1) ;
- if (p[1] < 0)
- {
- fd_close(p[0]) ;
- return 0 ;
- }
- fd_close(p[0]) ;
- if (p[1])
- {
- wait_pid(pid, &p[0]) ;
- errno = (unsigned char)c ;
- return 0 ;
- }
- return pid ;
+#else
+
+pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n)
+{
+ return cspawn_fork(prog, argv, envp, flags, fa, n) ;
}
#endif
diff --git a/src/sysdeps/tryposixspawnsetsid.c b/src/sysdeps/tryposixspawnsetsid.c
@@ -0,0 +1,30 @@
+/* ISC license. */
+
+#undef _POSIX_C_SOURCE
+#undef _XOPEN_SOURCE
+
+#ifndef _XPG4_2
+#define _XPG4_2
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE
+#endif
+
+#include <spawn.h>
+
+int main (void)
+{
+ pid_t pid ;
+ posix_spawn_file_actions_t actions ;
+ posix_spawnattr_t attr ;
+ char *const argv[2] = { "/bin/true", 0 } ;
+ char *const envp[1] = { 0 } ;
+ posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSID) ;
+ posix_spawn_file_actions_init(&actions) ;
+ return posix_spawn(&pid, argv[0], 0, 0, argv, envp) ;
+}