From: Luca Boccassi Date: Fri, 2 Jun 2023 15:06:17 +0000 (+0100) Subject: process-util: add posix_spawn helper X-Git-Tag: v255-rc1~250^2~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6ecdfe7d1008964eed3f67b489cef8c65a218bf1;p=thirdparty%2Fsystemd.git 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(). --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 4928379bd75..d0ffb2d6141 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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", diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 8f87fdc2ae7..0d50e797e53 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -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);