diff options
Diffstat (limited to 'src/basic/process-util.c')
-rw-r--r-- | src/basic/process-util.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 7cebbe1cc1..ed096900ac 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -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> @@ -1759,6 +1760,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", |