]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
process-util: add posix_spawn helper
authorLuca Boccassi <bluca@debian.org>
Fri, 2 Jun 2023 15:06:17 +0000 (16:06 +0100)
committerLuca Boccassi <bluca@debian.org>
Thu, 12 Oct 2023 12:37:22 +0000 (13:37 +0100)
This provides CLONE_VM + CLONE_VFORK semantics, so it is useful to
avoid CoW traps and other issues around doing work between fork()
and exec().

src/basic/process-util.c
src/basic/process-util.h

index 4928379bd757a8ffbc045f4d46a9aef2b8027f37..d0ffb2d61410a71b0225351b2ce855f16ff06cef 100644 (file)
@@ -5,6 +5,7 @@
 #include <limits.h>
 #include <linux/oom.h>
 #include <pthread.h>
+#include <spawn.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1732,6 +1733,51 @@ int make_reaper_process(bool b) {
         return 0;
 }
 
+int posix_spawn_wrapper(const char *path, char *const *argv, char *const *envp, pid_t *ret_pid) {
+        posix_spawnattr_t attr;
+        sigset_t mask;
+        pid_t pid;
+        int r;
+
+        /* Forks and invokes 'path' with 'argv' and 'envp' using CLONE_VM and CLONE_VFORK, which means the
+         * caller will be blocked until the child either exits or exec's. The memory of the child will be
+         * fully shared with the memory of the parent, so that there are no copy-on-write or memory.max
+         * issues. */
+
+        assert(path);
+        assert(argv);
+        assert(ret_pid);
+
+        assert_se(sigfillset(&mask) >= 0);
+
+        r = posix_spawnattr_init(&attr);
+        if (r != 0)
+                return -r; /* These functions return a positive errno on failure */
+        r = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK);
+        if (r != 0)
+                goto fail;
+        r = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF); /* Set all signals to SIG_DFL */
+        if (r != 0)
+                goto fail;
+        r = posix_spawnattr_setsigmask(&attr, &mask);
+        if (r != 0)
+                goto fail;
+
+        r = posix_spawn(&pid, path, NULL, &attr, argv, envp);
+        if (r != 0)
+                goto fail;
+
+        *ret_pid = pid;
+
+        posix_spawnattr_destroy(&attr);
+        return 0;
+
+fail:
+        assert(r > 0);
+        posix_spawnattr_destroy(&attr);
+        return -r;
+}
+
 static const char *const sigchld_code_table[] = {
         [CLD_EXITED] = "exited",
         [CLD_KILLED] = "killed",
index 8f87fdc2ae74f578fe129046668d7a0e8f925f77..0d50e797e536640fadff9b39e6933565c5fae9d4 100644 (file)
@@ -210,3 +210,5 @@ int get_process_threads(pid_t pid);
 
 int is_reaper_process(void);
 int make_reaper_process(bool b);
+
+int posix_spawn_wrapper(const char *path, char *const *argv, char *const *envp, pid_t *ret_pid);