1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-23 21:35:11 +03:00

process-util: add posix_spawn helper

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().
This commit is contained in:
Luca Boccassi 2023-06-02 16:06:17 +01:00
parent 58cb36e56b
commit 6ecdfe7d10
2 changed files with 48 additions and 0 deletions

View 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",

View 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);