}
if (ret) {
- if (FLAGS_SET(flags, _FORK_PID_ONLY))
+ r = pidref_set_pid(ret, pid);
+ if (r < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
*ret = PIDREF_MAKE_FROM_PID(pid);
- else {
- r = pidref_set_pid(ret, pid);
- if (r < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
- *ret = PIDREF_MAKE_FROM_PID(pid);
- }
}
return 1;
freeze();
if (ret) {
- if (FLAGS_SET(flags, _FORK_PID_ONLY))
- *ret = PIDREF_MAKE_FROM_PID(getpid_cached());
- else {
- r = pidref_set_self(ret);
- if (r < 0) {
- log_full_errno(prio, r, "Failed to acquire PID reference on ourselves: %m");
- _exit(EXIT_FAILURE);
- }
+ r = pidref_set_self(ret);
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to acquire PID reference on ourselves: %m");
+ _exit(EXIT_FAILURE);
}
}
return 0;
}
-int safe_fork_full(
- const char *name,
- const int stdio_fds[3],
- int except_fds[],
- size_t n_except_fds,
- ForkFlags flags,
- pid_t *ret) {
-
- _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
- int r;
-
- /* Getting the detached child process pid without pidfd is racy, so don't allow it if not returning
- * a pidref to the caller. */
- assert(!FLAGS_SET(flags, FORK_DETACH) || !ret);
-
- r = pidref_safe_fork_full(name, stdio_fds, except_fds, n_except_fds, flags|_FORK_PID_ONLY, ret ? &pidref : NULL);
- if (r < 0 || !ret)
- return r;
-
- *ret = pidref.pid;
-
- return r;
-}
-
int namespace_fork_full(
const char *outer_name,
const char *inner_name,
FORK_NEW_PIDNS = 1 << 21, /* Run child in its own PID namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
FORK_FREEZE = 1 << 22, /* Don't return in child, just call freeze() instead */
FORK_ALLOW_DLOPEN = 1 << 23, /* Do not block dlopen() in child */
-
- _FORK_PID_ONLY = 1 << 24, /* Don't open a pidfd referencing the child process */
} ForkFlags;
int pidref_safe_fork_full(
return pidref_safe_fork_full(name, NULL, NULL, 0, flags, ret);
}
-int safe_fork_full(
- const char *name,
- const int stdio_fds[3],
- int except_fds[],
- size_t n_except_fds,
- ForkFlags flags,
- pid_t *ret);
-
-static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret) {
- return safe_fork_full(name, NULL, NULL, 0, flags, ret);
-}
-
int namespace_fork_full(
const char *outer_name,
const char *inner_name,
* child's PID, we are PID1/autoreaper after all, hence when it dies we'll automatically clean it up
* anyway. */
- r = safe_fork_full("(sd-expire)",
- /* stdio_fds= */ NULL,
- (int[]) { dev_autofs_fd, ioctl_fd },
- /* n_except_fds= */ 2,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
- /* ret= */ NULL);
+ r = pidref_safe_fork_full(
+ "(sd-expire)",
+ /* stdio_fds= */ NULL,
+ (int[]) { dev_autofs_fd, ioctl_fd },
+ /* n_except_fds= */ 2,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
+ /* ret= */ NULL);
if (r != 0)
return r;
parent_pid = getpid_cached();
- r = safe_fork("(sd-pam)", 0, NULL);
+ r = pidref_safe_fork("(sd-pam)", /* flags= */ 0, /* ret= */ NULL);
if (r < 0)
goto fail;
if (r == 0) {
if (is_dir("/tmp", /* follow= */ false) > 0 && !MANAGER_IS_TEST_RUN(m))
flags |= FORK_PRIVATE_TMP;
- r = safe_fork("(sd-gens)", flags, NULL);
+ r = pidref_safe_fork("(sd-gens)", flags, /* ret= */ NULL);
if (r == 0) {
r = manager_execute_generators(m, paths, /* remount_ro= */ true);
_exit(r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE);
static int unpeel_get_fd(const char *mount_path, int *ret_fd) {
_cleanup_close_pair_ int pipe_fds[2] = EBADF_PAIR;
_cleanup_close_ int fs_fd = -EBADF;
- pid_t pid;
int r;
assert(mount_path);
return log_debug_errno(errno, "Failed to create socket pair: %m");
/* Clone mount namespace here to unpeel without affecting live process */
- r = safe_fork("(sd-ns-unpeel)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &pid);
+ r = pidref_safe_fork("(sd-ns-unpeel)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
* overlays to obtain FDs the underlying directories, over which we will reapply the overlays
* 3. In the child again, receive the FDs and reapply the overlays
*/
- r = safe_fork("(sd-ns-refresh-exts)",
- FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE,
- NULL);
+ r = pidref_safe_fork(
+ "(sd-ns-refresh-exts)",
+ FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
int unit_fork_helper_process_full(Unit *u, const char *name, bool into_cgroup, ForkFlags flags, PidRef *ret) {
CGroupRuntime *crt = NULL;
- pid_t pid;
int r;
assert(u);
assert(ret);
/* Forks off a helper process and makes sure it is a member of the unit's cgroup, if configured to
- * do so. Returns == 0 in the child, and > 0 in the parent. The pid parameter is always filled in
- * with the child's PID. */
+ * do so. Returns == 0 in the child, and > 0 in the parent. The pidref parameter is always filled in
+ * with the child's PID reference. */
if (into_cgroup) {
r = unit_realize_cgroup(u);
crt = unit_get_cgroup_runtime(u);
}
- r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|flags, &pid);
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|flags, &pidref);
if (r < 0)
return r;
if (r > 0) {
- _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
- int q;
-
- /* Parent */
-
- q = pidref_set_pid(&pidref, pid);
- if (q < 0)
- return q;
-
*ret = TAKE_PIDREF(pidref);
return r;
}
}
}
+ *ret = TAKE_PIDREF(pidref);
return 0;
}
return log_error_errno(r, "Failed to unlock loopback block device: %m");
}
- rcode = safe_fork("(with)", FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL);
+ rcode = pidref_safe_fork("(with)", FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, /* ret= */ NULL);
if (rcode == 0) {
/* Child */
assert(h->uid > 0); /* We never should be UID 0 */
/* Let's kill everything matching the specified UID */
- r = safe_fork("(sd-killer)",
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG,
- NULL);
+ r = pidref_safe_fork(
+ "(sd-killer)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
if (!uid_is_valid(h->uid))
return 0;
- r = safe_fork("(sd-delkey)",
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
- NULL);
+ r = pidref_safe_fork(
+ "(sd-delkey)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
/* Also install the access key in the user's own keyring */
if (uid_is_valid(h->uid)) {
- r = safe_fork("(sd-addkey)",
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
- NULL);
+ r = pidref_safe_fork(
+ "(sd-addkey)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
+ /* ret= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to install encryption key in user's keyring: %m");
if (r == 0) {
assert(tree_fd >= 0);
assert(userns_fd >= 0);
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"mangle-tree",
/* stdio_fds= */ NULL,
(int[]) { userns_fd, tree_fd }, 2,
if (r < 0)
return r;
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"copy-tree",
/* stdio_fds= */ NULL,
(int[]) { *userns_fd, source_fd, target_fd }, 3,
if (r < 0)
return r;
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"rm-tree",
/* stdio_fds= */ NULL,
(int[]) { *userns_fd, tree_fd }, 2,
**********************************************************************/
static int spawn_child(const char *child, char **argv) {
- pid_t child_pid;
int fd[2], r;
if (pipe(fd) < 0)
return log_error_errno(errno, "Failed to create pager pipe: %m");
- r = safe_fork_full("(remote)",
- (int[]) {STDIN_FILENO, fd[1], STDERR_FILENO },
- NULL, 0,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &child_pid);
+ r = pidref_safe_fork_full(
+ "(remote)",
+ (int[]) {STDIN_FILENO, fd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ /* ret= */ NULL);
if (r < 0) {
safe_close_pair(fd);
return r;
if (pipe2(pfd, O_CLOEXEC) < 0)
return -errno;
- r = safe_fork("(sd-setresuid)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_WAIT, /* ret= */ NULL);
+ r = pidref_safe_fork(
+ "(sd-setresuid)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_WAIT,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
assert_se(bus->n_ref == 1);
/* Check that after a fork the cleanup functions return NULL */
- r = safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
+ r = pidref_safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
if (r == 0) {
assert_se(bus);
ASSERT_RETURN_EXPECTED_SE(sd_bus_is_ready(bus) == -ECHILD);
if (running_in_chroot() > 0)
return (void) log_tests_skipped("Running in chroot");
- ASSERT_OK(r = safe_fork("(mdio_bus)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL));
+ r = ASSERT_OK(pidref_safe_fork(
+ "(mdio_bus)",
+ FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE,
+ NULL));
if (r == 0) {
const char *syspath = "/sys/bus/mdio_bus/drivers/Qualcomm Atheros AR8031!AR8033";
const char *id = "+drivers:mdio_bus:Qualcomm Atheros AR8031!AR8033";
ASSERT_OK_ZERO(sd_event_prepare(e));
/* Check that after a fork the cleanup functions return NULL */
- r = safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
+ r = pidref_safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
if (r == 0) {
ASSERT_NOT_NULL(e);
ASSERT_NULL(sd_event_ref(e));
assert_se(sd_journal_seek_head(j) == 0);
assert_se(j->current_location.type == LOCATION_HEAD);
- r = safe_fork("(journal-fork-test)", FORK_WAIT|FORK_LOG, NULL);
+ r = pidref_safe_fork("(journal-fork-test)", FORK_WAIT|FORK_LOG, NULL);
if (r == 0) {
assert_se(j);
ASSERT_RETURN_EXPECTED_SE(sd_journal_get_realtime_usec(j, NULL) == -ECHILD);
int locale_gen_run(void) {
#if HAVE_LOCALEGEN
- pid_t pid;
int r;
- r = safe_fork("(sd-localegen)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, &pid);
+ r = pidref_safe_fork(
+ "(locale-gen)",
+ FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
#include "alloc-util.h"
#include "bus-message-util.h"
#include "device-util.h"
+#include "event-util.h"
#include "format-util.h"
#include "hash-funcs.h"
#include "logind.h"
sd_device *device;
char *path;
- pid_t child;
-
uint32_t brightness;
bool again;
assert(s);
assert(si);
- assert(si->si_pid == w->child);
- w->child = 0;
w->child_event_source = sd_event_source_unref(w->child_event_source);
brightness_writer_reply(w,
assert(w);
assert(w->manager);
- assert(w->child == 0);
assert(!w->child_event_source);
- r = safe_fork("(sd-bright)", FORK_DEATHSIG_SIGKILL|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
+ _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork(
+ "(sd-bright)",
+ FORK_DEATHSIG_SIGKILL|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG,
+ &pidref);
if (r < 0)
return r;
if (r == 0) {
_exit(EXIT_SUCCESS);
}
- r = sd_event_add_child(w->manager->event, &w->child_event_source, w->child, WEXITED, on_brightness_writer_exit, w);
+ r = event_add_child_pidref(w->manager->event, &w->child_event_source, &pidref, WEXITED, on_brightness_writer_exit, w);
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch brightness writer child " PID_FMT ": %m", pidref.pid);
+
+ r = sd_event_source_set_child_process_own(w->child_event_source, true);
if (r < 0)
- return log_error_errno(r, "Failed to watch brightness writer child " PID_FMT ": %m", w->child);
+ return log_error_errno(r, "Failed to take ownership of child process: %m");
+
+ pidref_done(&pidref);
return 0;
}
#include "log.h"
#include "mountfsd-manager.h"
#include "pidfd-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "set.h"
#include "signal-util.h"
static int start_one_worker(Manager *m) {
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *source = NULL;
bool fixed;
- pid_t pid;
int r;
assert(m);
fixed = set_size(m->workers_fixed) < MOUNTFS_WORKERS_MIN;
- r = safe_fork_full(
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork_full(
"(sd-worker)",
/* stdio_fds= */ NULL,
&m->listen_fd, 1,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_CLOSE_ALL_FDS,
- &pid);
+ &pidref);
if (r < 0)
return log_error_errno(r, "Failed to fork new worker child: %m");
if (r == 0) {
safe_close(m->listen_fd);
}
- r = setenvf("LISTEN_PID", /* overwrite= */ true, PID_FMT, pid);
+ r = setenvf("LISTEN_PID", /* overwrite= */ true, PID_FMT, pidref.pid);
if (r < 0) {
log_error_errno(r, "Failed to set $LISTEN_PID: %m");
_exit(EXIT_FAILURE);
_exit(EXIT_FAILURE);
}
- r = sd_event_add_child(m->event, &source, pid, WEXITED, on_worker_exit, m);
+ r = event_add_child_pidref(m->event, &source, &pidref, WEXITED, on_worker_exit, m);
if (r < 0)
- return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pid);
+ return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pidref.pid);
r = set_ensure_put(
fixed ? &m->workers_fixed : &m->workers_dynamic,
assert(netns_fd >= 0);
- r = safe_fork("(sd-netns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
+ r = pidref_safe_fork(
+ "(sd-netns)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE,
+ /* ret= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to fork process (sd-netns): %m");
if (r == 0) {
#include "nsresourced-manager.h"
#include "parse-util.h"
#include "pidfd-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "recurse-dir.h"
#include "set.h"
static int start_one_worker(Manager *m) {
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *source = NULL;
bool fixed;
- pid_t pid;
int r;
assert(m);
fixed = set_size(m->workers_fixed) < NSRESOURCE_WORKERS_MIN;
- r = safe_fork_full(
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork_full(
"(sd-worker)",
/* stdio_fds= */ NULL,
&m->listen_fd, 1,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_CLOSE_ALL_FDS,
- &pid);
+ &pidref);
if (r < 0)
return log_error_errno(r, "Failed to fork new worker child: %m");
if (r == 0) {
safe_close(m->listen_fd);
}
- r = setenvf("LISTEN_PID", /* overwrite= */ true, PID_FMT, pid);
+ r = setenvf("LISTEN_PID", /* overwrite= */ true, PID_FMT, pidref.pid);
if (r < 0) {
log_error_errno(r, "Failed to set $LISTEN_PID: %m");
_exit(EXIT_FAILURE);
_exit(EXIT_FAILURE);
}
- r = sd_event_add_child(m->event, &source, pid, WEXITED, on_worker_exit, m);
+ r = event_add_child_pidref(m->event, &source, &pidref, WEXITED, on_worker_exit, m);
if (r < 0)
- return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pid);
+ return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pidref.pid);
r = set_ensure_put(
fixed ? &m->workers_fixed : &m->workers_dynamic,
#include "oomd-util.h"
#include "parse-util.h"
#include "path-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "set.h"
#include "tests.h"
return saved_result;
}
-static int fork_and_sleep(unsigned sleep_min) {
- pid_t pid;
+static int fork_and_sleep(unsigned sleep_min, PidRef *ret) {
int r;
- ASSERT_OK(r = safe_fork("(test-oom-child)", /* flags= */ 0, &pid));
+ r = pidref_safe_fork("(test-oom-child)", FORK_LOG|FORK_DEATHSIG_SIGKILL, ret);
if (r == 0) {
usec_t timeout = usec_add(now(CLOCK_MONOTONIC), sleep_min * USEC_PER_MINUTE);
for (;;) {
}
}
- return pid;
+ return r;
}
TEST(oomd_cgroup_kill) {
/* Do this twice to also check the increment behavior on the xattrs */
for (size_t i = 0; i < 2; i++) {
_cleanup_free_ char *v = NULL;
- pid_t pid[2];
+ _cleanup_(pidref_done) PidRef one = PIDREF_NULL, two = PIDREF_NULL;
- for (size_t j = 0; j < 2; j++) {
- pid[j] = fork_and_sleep(5);
- ASSERT_OK(cg_attach(subcgroup, pid[j]));
- }
+ ASSERT_OK(fork_and_sleep(5, &one));
+ ASSERT_OK(cg_attach(subcgroup, one.pid));
+ ASSERT_OK(fork_and_sleep(5, &two));
+ ASSERT_OK(cg_attach(subcgroup, two.pid));
ASSERT_OK_POSITIVE(oomd_cgroup_kill(subcgroup, false /* recurse */, false /* dry run */));
return log_oom();
}
- r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL);
+ r = pidref_safe_fork(
+ "(quotacheck)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
#include "main-func.h"
#include "mount-setup.h"
#include "path-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "signal-util.h"
}
static int do_remount(const char *path, bool force_rw, Hashmap **pids) {
- pid_t pid;
int r;
assert(path);
log_debug("Remounting %s...", path);
- r = safe_fork(force_rw ? "(remount-rw)" : "(remount)",
- FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork(
+ force_rw ? "(remount-rw)" : "(remount)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG,
+ &pidref);
if (r < 0)
return r;
if (r == 0) {
}
/* Parent */
- return track_pid(pids, path, pid);
+ return track_pid(pids, path, pidref.pid);
}
static int remount_by_fstab(Hashmap **ret_pids) {
(void) dlopen_libmount();
- r = safe_fork("(sd-copy)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
+ r = pidref_safe_fork(
+ "(sd-copy)",
+ FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
-#include <sys/wait.h>
#include <unistd.h>
#include "sd-event.h"
#include "fd-util.h"
#include "log.h"
#include "path-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "random-util.h"
#include "resolved-dns-server.h"
* Spawns a DNS TLS server using the command line "openssl s_server" tool.
*/
static void *tls_dns_server(void *p) {
- pid_t openssl_pid;
int r;
_cleanup_close_ int fd_server = -EBADF, fd_tls = -EBADF;
_cleanup_free_ char *cert_path = NULL, *key_path = NULL;
fd_tls = fd[1];
}
- r = safe_fork_full("(test-resolved-stream-tls-openssl)",
- (int[]) { fd_tls, fd_tls, STDOUT_FILENO },
- NULL, 0,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG,
- &openssl_pid);
- assert_se(r >= 0);
+ _cleanup_(pidref_done) PidRef openssl_pidref = PIDREF_NULL;
+ r = ASSERT_OK(pidref_safe_fork_full(
+ "(test-resolved-stream-tls-openssl)",
+ (int[]) { fd_tls, fd_tls, STDOUT_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG,
+ &openssl_pidref));
if (r == 0) {
/* Child */
execlp("openssl", "openssl", "s_server", "-accept", bind_str,
/* Once the test is done kill the TLS server to release the port */
assert_se(pthread_mutex_lock(server_lock) == 0);
- assert_se(kill(openssl_pid, SIGTERM) >= 0);
- assert_se(waitpid(openssl_pid, NULL, 0) >= 0);
+ assert_se(pidref_kill(&openssl_pidref, SIGTERM) >= 0);
+ assert_se(pidref_wait_for_terminate(&openssl_pidref, NULL) >= 0);
assert_se(pthread_mutex_unlock(server_lock) == 0);
}
/* First test if CLONE_NEWUSER/CLONE_NEWNET can actually work for us, i.e. we can open the namespaces
* and then still access the build dir we are run from. We do that in a child process since it's
* nasty if we have to go back from the namespace once we entered it and realized it cannot work. */
- r = safe_fork("(usernstest)", FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT, NULL);
+ r = pidref_safe_fork("(usernstest)", FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) { /* child */
_cleanup_free_ char *rt = NULL, *d = NULL;
/* Forks off a child that destroys the specified path. This will be best effort only, i.e. the child
* will attempt to do its thing, but we won't wait for it or check its success. */
- r = safe_fork("(sd-rmrf)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DETACH, NULL);
+ r = pidref_safe_fork("(sd-rmrf)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DETACH, /* ret= */ NULL);
if (r != 0)
return r;
if (r < 0)
return r;
/* Fork off child that moves into userns and does the copying */
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"rm-tree",
/* stdio_fds= */ NULL,
(int[]) { userns_fd, tree_fd, }, 2,
return r;
/* Fork off child that moves into userns and does the copying */
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"clone-tree",
/* stdio_fds= */ NULL,
(int[]) { userns_fd, tree_fd, target_fd }, 3,
assert(context);
- r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT, NULL);
+ r = pidref_safe_fork(
+ "(editor)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) { /* Child */
* bound since the core files have an upper size limit. It's also not doing any
* system call or interacting with the system in any way, besides reading from
* the file descriptor and writing into these four pipes. */
- r = safe_fork_full("(sd-parse-elf)",
- NULL,
+ r = pidref_safe_fork_full("(sd-parse-elf)",
+ /* stdio_fds= */ NULL,
(int[]){ fd, error_pipe[1], return_pipe[1], package_metadata_pipe[1], dlopen_metadata_pipe[1] },
5,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
- NULL);
+ /* ret= */ NULL);
if (r < 0) {
if (r == -EPROTO) { /* We should have the errno from the child, but don't clobber original error */
ssize_t k;
if (strv_extend(&argv, "::") < 0)
return log_oom();
- r = safe_fork("(mcopy)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, NULL);
+ r = pidref_safe_fork(
+ "(mcopy)",
+ FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
log_debug("Executing mkfs command: %s", strna(j));
}
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"(mkfs)",
stdio_fds,
/* except_fds= */ NULL,
return log_debug_errno(errno, "Failed to open pipe: %m");
/* Fork a child. Note that we set FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE here, i.e. get a new mount namespace */
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"(sd-clonemnt)",
/* stdio_fds= */ NULL,
(int[]) { mount_fd, transfer_fds[1], errno_pipe_fds[1] }, 3,
#include "strv.h"
#include "terminal-util.h"
-static pid_t pager_pid = 0;
+static PidRef pager_pidref = PIDREF_NULL;
static int stored_stdout = -1;
static int stored_stderr = -1;
if (flags & PAGER_DISABLE)
return;
- if (pager_pid > 0)
+ if (pidref_is_set(&pager_pidref))
return;
if (terminal_is_dumb())
}
/* We set SIGINT as PR_DEATHSIG signal here, to match the "K" parameter we set in $LESS, which enables SIGINT behaviour. */
- r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGINT|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pager_pid);
+ r = pidref_safe_fork(
+ "(pager)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGINT|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG,
+ &pager_pidref);
if (r < 0)
return;
if (r == 0) {
void pager_close(void) {
- if (pager_pid <= 0)
+ if (!pidref_is_set(&pager_pidref))
return;
/* Inform pager that we are done */
stored_stderr = safe_close(stored_stderr);
stdout_redirected = stderr_redirected = false;
- (void) kill(pager_pid, SIGCONT);
- _cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pager_pid);
- (void) pidref_set_pid(&pidref, pager_pid);
- (void) pidref_wait_for_terminate(&pidref, NULL);
- TAKE_PID(pager_pid);
+ (void) pidref_kill(&pager_pidref, SIGCONT);
+ (void) pidref_wait_for_terminate(&pager_pidref, /* ret_si= */ NULL);
+ pidref_done(&pager_pidref);
}
bool pager_have(void) {
- return pager_pid > 0;
+ return pidref_is_set(&pager_pidref);
}
int show_man_page(const char *desc, bool null_stdio) {
/* We cheat and exec kexec to avoid doing all its work */
log_info("Rebooting with kexec.");
- r = safe_fork("(sd-kexec)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL);
+ r = pidref_safe_fork(
+ "(sd-kexec)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT,
+ /* ret= */ NULL);
if (r == 0) {
/* Child */
#include "log.h"
#include "main-func.h"
#include "pidfd-util.h"
+#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
#include "socket-netlink.h"
static int fork_and_exec_process(char * const *argv, int fd) {
_cleanup_free_ char *joined = NULL;
- pid_t child_pid;
int r;
assert(!strv_isempty(argv));
if (!joined)
return log_oom();
- r = safe_fork("(activate)",
- FORK_RESET_SIGNALS | FORK_DEATHSIG_SIGTERM | FORK_RLIMIT_NOFILE_SAFE | FORK_LOG,
- &child_pid);
+ _cleanup_(pidref_done) PidRef child_pidref = PIDREF_NULL;
+ r = pidref_safe_fork(
+ "(activate)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG,
+ &child_pidref);
if (r < 0)
return r;
if (r == 0) {
_exit(EXIT_FAILURE);
}
- log_info("Spawned '%s' as PID " PID_FMT ".", joined, child_pid);
+ log_info("Spawned '%s' as PID " PID_FMT ".", joined, child_pidref.pid);
return 0;
}
return r;
need_to_reload = r > 0;
- r = safe_fork("(sd-unmerge)", FORK_WAIT|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, /* ret= */ NULL);
+ r = pidref_safe_fork(
+ "(sd-unmerge)",
+ FORK_WAIT|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
_cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL;
const BootEntry *e;
- pid_t pid;
int r;
if (kexec_loaded()) {
if (arg_dry_run)
return 0;
- r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ r = pidref_safe_fork(
+ "(kexec)",
+ FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG,
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
log_info("/* %s(%s) */", __func__, p);
- r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
if (r == 0) {
/* child */
TEST(rename_process_multi) {
int r;
- r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
if (r == 0) {
/* child */
asynchronous_close(fd);
wait_fd_closed(fd);
- r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(subreaper)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT,
+ NULL));
if (r == 0) {
/* child */
/* Do this once more, from a subreaper. Which is nice, because we can watch the async child even
* though detached */
- r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(subreaper)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT,
+ NULL));
if (r == 0) {
_cleanup_free_ char *tt = NULL, *kk = NULL;
if (r <= 0)
return (void) log_tests_skipped("Lacking CAP_LINUX_IMMUTABLE, skipping getambient test.");
- r = safe_fork("(getambient)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(getambient)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG,
+ NULL));
if (r == 0) {
int x, y;
TEST(getenv_steal_erase) {
int r;
- r = safe_fork("(sd-getenvstealerase)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
+ r = pidref_safe_fork("(sd-getenvstealerase)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) {
_cleanup_strv_free_ char **l = NULL;
#include "cpu-set-util.h"
#include "dropin.h"
#include "errno-list.h"
+#include "event-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
}
static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
- pid_t *pid = userdata;
+ PidRef *pidref = ASSERT_PTR(userdata);
- ASSERT_NOT_NULL(pid);
-
- (void) kill(*pid, SIGKILL);
+ (void) pidref_kill(pidref, SIGKILL);
return 1;
}
_cleanup_close_pair_ int outpipe[2] = EBADF_PAIR, errpipe[2] = EBADF_PAIR;
_cleanup_strv_free_ char **libraries = NULL;
_cleanup_free_ char *result = NULL;
- pid_t pid;
int r;
ASSERT_NOT_NULL(exec);
ASSERT_OK_ERRNO(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC));
ASSERT_OK_ERRNO(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC));
- r = safe_fork_full("(spawn-ldd)",
- (int[]) { -EBADF, outpipe[1], errpipe[1] },
- NULL, 0,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork_full(
+ "(spawn-ldd)",
+ (int[]) { -EBADF, outpipe[1], errpipe[1] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
+ &pidref);
ASSERT_OK(r);
if (r == 0) {
execlp("ldd", "ldd", exec, NULL);
ASSERT_OK(sd_event_new(&e));
ASSERT_OK(sd_event_add_time_relative(e, NULL, CLOCK_MONOTONIC,
- 10 * USEC_PER_SEC, USEC_PER_SEC, on_spawn_timeout, &pid));
+ 10 * USEC_PER_SEC, USEC_PER_SEC, on_spawn_timeout, &pidref));
ASSERT_OK(sd_event_add_io(e, &stdout_source, outpipe[0], EPOLLIN, on_spawn_io, &result));
ASSERT_OK(sd_event_source_set_enabled(stdout_source, SD_EVENT_ONESHOT));
ASSERT_OK(sd_event_add_io(e, &stderr_source, errpipe[0], EPOLLIN, on_spawn_io, NULL));
ASSERT_OK(sd_event_source_set_enabled(stderr_source, SD_EVENT_ONESHOT));
- ASSERT_OK(sd_event_add_child(e, &sigchld_source, pid, WEXITED, on_spawn_exit, NULL));
+ ASSERT_OK(event_add_child_pidref(e, &sigchld_source, &pidref, WEXITED, on_spawn_exit, NULL));
/* Child exit should be processed after IO is complete */
ASSERT_OK(sd_event_source_set_priority(sigchld_source, SD_EVENT_PRIORITY_NORMAL + 1));
static int prepare_ns(const char *process_name) {
int r;
- r = safe_fork(process_name,
- FORK_RESET_SIGNALS |
- FORK_CLOSE_ALL_FDS |
- FORK_DEATHSIG_SIGTERM |
- FORK_WAIT |
- FORK_REOPEN_LOG |
- FORK_LOG |
- FORK_NEW_MOUNTNS |
- FORK_MOUNTNS_SLAVE,
- NULL);
+ r = pidref_safe_fork(
+ process_name,
+ FORK_RESET_SIGNALS|
+ FORK_CLOSE_ALL_FDS|
+ FORK_DEATHSIG_SIGTERM|
+ FORK_WAIT|
+ FORK_REOPEN_LOG|
+ FORK_LOG|
+ FORK_NEW_MOUNTNS|
+ FORK_MOUNTNS_SLAVE,
+ NULL);
ASSERT_OK(r);
if (r == 0) {
_cleanup_free_ char *unit_dir = NULL, *build_dir = NULL, *build_dir_mount = NULL;
}
TEST(rearrange_stdio) {
- pid_t pid;
int r;
- r = safe_fork("rearrange", FORK_WAIT|FORK_LOG, &pid);
+ r = pidref_safe_fork("rearrange", FORK_WAIT|FORK_LOG, NULL);
assert_se(r >= 0);
if (r == 0) {
}
TEST(close_all_fds) {
+ ForkFlags flags = FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT;
int r;
- ASSERT_OK(r = safe_fork("(caf-plain)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(caf-plain)", flags, NULL));
if (r == 0) {
test_close_all_fds_inner(close_all_fds);
_exit(EXIT_SUCCESS);
}
- ASSERT_OK(r = safe_fork("(caf-nomalloc)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
+ ASSERT_OK(r = pidref_safe_fork("(caf-nomalloc)", flags, NULL));
if (r == 0) {
test_close_all_fds_inner(close_all_fds_without_malloc);
_exit(EXIT_SUCCESS);
}
- ASSERT_OK(r = safe_fork("(caf-proc)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
+ ASSERT_OK(r = pidref_safe_fork("(caf-proc)", flags, NULL));
if (r == 0) {
test_close_all_fds_inner(close_all_fds_by_proc);
_exit(EXIT_SUCCESS);
}
- ASSERT_OK(r = safe_fork("(caf-frugal)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
+ ASSERT_OK(r = pidref_safe_fork("(caf-frugal)", flags, NULL));
if (r == 0) {
test_close_all_fds_inner(close_all_fds_frugal);
_exit(EXIT_SUCCESS);
#include "bus-locator.h"
#include "bus-wait-for-jobs.h"
+#include "event-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "hashmap.h"
#include "path-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "random-util.h"
#include "rm-rf.h"
_cleanup_free_ char *scope = NULL;
const char *object;
int r;
- pid_t pid;
r = sd_bus_open_system(&bus);
if (r < 0)
assert_se(pipe2(pipe_fd, O_CLOEXEC) >= 0);
- r = safe_fork("(eat-memory)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &pid);
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork("(eat-memory)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &pidref);
assert_se(r >= 0);
if (r == 0) {
real_pressure_eat_memory(pipe_fd[0]);
_exit(EXIT_SUCCESS);
}
- assert_se(sd_event_add_child(e, &cs, pid, WEXITED, real_pressure_child_callback, NULL) >= 0);
+ assert_se(event_add_child_pidref(e, &cs, &pidref, WEXITED, real_pressure_child_callback, NULL) >= 0);
assert_se(sd_event_source_set_child_process_own(cs, true) >= 0);
assert_se(unsetenv("MEMORY_PRESSURE_WATCH") >= 0);
p = mfree(p);
ASSERT_NOT_NULL(p = path_join(tmp, "zero-mode/should-fail-to-create-child"));
ASSERT_OK(mkdir_parents_safe(tmp, p, 0000, UID_INVALID, GID_INVALID, 0));
- ASSERT_OK(r = safe_fork("(test-mkdir-no-cap)", FORK_DEATHSIG_SIGTERM | FORK_WAIT | FORK_LOG, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(test-mkdir-no-cap)", FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL));
if (r == 0) {
(void) capability_bounding_set_drop(0, /* right_now= */ true);
ASSERT_ERROR(mkdir_p_safe(tmp, p, 0000, UID_INVALID, GID_INVALID, 0), EACCES);
assert_se(mkdir(subdir, 0755) >= 0);
FOREACH_STRING(p, "/usr", "/sys", "/", tmp) {
- ASSERT_OK(r = safe_fork("(bind-remount-recursive)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(bind-remount-recursive)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
struct statvfs svfs;
CHECK_PRIV;
- ASSERT_OK(r = safe_fork("(remount-one-with-mountinfo)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(remount-one-with-mountinfo)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
_exit(EXIT_SUCCESS);
}
- ASSERT_OK(r = safe_fork("(remount-one)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(remount-one)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
assert_se(bind_remount_one("/run", MS_RDONLY, MS_RDONLY) >= 0);
assert_se(bind_remount_one("/run", MS_NOEXEC, MS_RDONLY|MS_NOEXEC) >= 0);
};
FOREACH_ELEMENT(i, table) {
- ASSERT_OK(r = safe_fork("(switch-root)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(switch-root)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
assert_se(make_mount_point(i->path) >= 0);
assert_se(mount_switch_root_full(i->path, /* mount_propagation_flag= */ 0, i->force_ms_move) >= 0);
CHECK_PRIV;
FOREACH_ELEMENT(t, test_table) {
- ASSERT_OK(r = safe_fork("(umount-rec)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(umount-rec)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
_cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
assert_se(s);
assert_se(mkdir(s, 0700) >= 0);
- ASSERT_OK(r = safe_fork("(make-mount-point)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(make-mount-point)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
assert_se(mkdtemp_malloc(NULL, &a) >= 0);
assert_se(mkdtemp_malloc(NULL, &b) >= 0);
- ASSERT_OK(r = safe_fork("(bind-mount-submounts)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(bind-mount-submounts)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
char *x;
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
assert_se(mkdtemp_malloc("/tmp/test-mount-util.path_is_network_fs_harder.XXXXXXX", &t) >= 0);
- ASSERT_OK(r = safe_fork("(path-is-network-fs-harder)", FORK_COMMON_FLAGS, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(path-is-network-fs-harder)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
ASSERT_OK(mount_nofollow_verbose(LOG_INFO, "tmpfs", t, "tmpfs", 0, NULL));
ASSERT_OK_ZERO(path_is_network_fs_harder(t));
/* Set up a socket pair to transfer the mount fd from the child (in a different mountns) to us. */
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, fds));
- r = ASSERT_OK(safe_fork_full(
+ r = ASSERT_OK(pidref_safe_fork_full(
"(mount-fd-clone-setup)",
/* stdio_fds= */ NULL,
&fds[1], 1,
_cleanup_free_ char *target = ASSERT_NOT_NULL(path_join(t, "target"));
ASSERT_OK_ERRNO(mkdir(target, 0755));
- r = ASSERT_OK(safe_fork_full(
+ r = ASSERT_OK(pidref_safe_fork_full(
"(mount-fd-clone-verify)",
/* stdio_fds= */ NULL,
&first_clone, 1,
}
ASSERT_OK(r);
- r = ASSERT_OK(safe_fork("(protect)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork("(protect)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
if (r == 0) {
_cleanup_close_ int fd = -EBADF;
/* Testing with several syscalls filtered, and check if the nss modules gracefully handle failures in
* masked syscalls. See issue #38582. */
- r = ASSERT_OK(safe_fork("(with-seccomp)", FORK_LOG|FORK_WAIT, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork("(with-seccomp)", FORK_LOG|FORK_WAIT, /* ret= */ NULL));
if (r == 0) {
_cleanup_hashmap_free_ Hashmap *filter = NULL;
ASSERT_NOT_NULL(filter = hashmap_new(NULL));
if (path_is_absolute(path))
ASSERT_STREQ(t, path);
- r = ASSERT_OK(safe_fork("(find-exec)", FORK_LOG|FORK_DEATHSIG_SIGKILL|FORK_WAIT, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork(
+ "(find-exec)",
+ FORK_LOG|FORK_DEATHSIG_SIGKILL|FORK_WAIT,
+ /* ret= */ NULL));
if (r == 0) {
r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL));
}
#endif
- r = ASSERT_OK(safe_fork("(cmdline)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork("(cmdline)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
if (r == 0) {
r = detach_mount_namespace();
if (r < 0) {
ASSERT_EQ(a, b);
ASSERT_EQ(a, c);
- r = ASSERT_OK(safe_fork("(getpid)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
+ r = ASSERT_OK(pidref_safe_fork("(getpid)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret= */ NULL));
if (r == 0) {
/* In child */
log_info("getpid_cached(): %lf μs each", (double) q / iterations);
}
-TEST(safe_fork) {
+TEST(pidref_safe_fork) {
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
siginfo_t status;
pid_t pid;
int r;
- r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
+ r = pidref_safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &child);
ASSERT_OK(r);
if (r == 0) {
_exit(88);
}
- _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
- ASSERT_OK(pidref_set_pid(&child, pid));
-
ASSERT_OK(pidref_wait_for_terminate(&child, &status));
ASSERT_EQ(status.si_code, CLD_EXITED);
ASSERT_EQ(status.si_status, 88);
TEST(setpriority_closest) {
int r;
- r = safe_fork("(test-setprio)",
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG, NULL);
+ r = pidref_safe_fork(
+ "(test-setprio)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG,
+ NULL);
ASSERT_OK(r);
if (r == 0) {
int r;
/* Run this test in a child, so that we can guarantee there's exactly one thread around in the child */
- r = safe_fork("(nthreads)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
+ r = pidref_safe_fork(
+ "(nthreads)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG,
+ NULL);
ASSERT_OK(r);
if (r == 0) {
TEST(is_reaper_process) {
int r;
- r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(regular)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT,
+ NULL));
if (r == 0) {
/* child */
_exit(EXIT_SUCCESS);
}
- r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(newpid)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT,
+ NULL));
if (r == 0) {
/* child */
}
}
- r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(newpid1)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT,
+ NULL));
if (r == 0) {
/* grandchild, which is PID1 in a pidns */
ASSERT_OK_EQ(getpid_cached(), 1);
_exit(EXIT_SUCCESS);
}
- r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT, NULL);
- ASSERT_OK(r);
+ r = ASSERT_OK(pidref_safe_fork(
+ "(subreaper)",
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_WAIT,
+ NULL));
if (r == 0) {
/* child */
ASSERT_OK(make_reaper_process(true));
_cleanup_close_ int memfd = memfd_new_and_seal("sfdisk", definition, SIZE_MAX);
ASSERT_OK(memfd);
- r = safe_fork_full(
+ r = pidref_safe_fork_full(
"(sfdisk)",
(int[]) { memfd, STDOUT_FILENO, STDERR_FILENO },
/* except_fds= */ NULL,
assert_se(getrlimit(resource, &direct) >= 0);
/* We fork off a child so that getrlimit() doesn't work anymore */
- r = safe_fork("(getrlimit)",
- FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT,
- /* ret= */ NULL);
+ r = pidref_safe_fork(
+ "(getrlimit)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT,
+ /* ret= */ NULL);
assert_se(r >= 0);
if (r == 0) {
/* This test only works unpriv (as only then the access mask for the owning user matters),
* hence drop privs here */
- ASSERT_OK(r = safe_fork("(setresuid)", FORK_DEATHSIG_SIGTERM|FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(setresuid)", FORK_DEATHSIG_SIGTERM|FORK_WAIT, NULL));
if (r == 0) {
/* child */
log_info("Testing %s", syscall_filter_sets[i].name);
- ASSERT_OK(r = safe_fork("(filter_sets)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(filter_sets)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
int fd;
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(restrict-namespace)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(restrict-namespace)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
assert_se(seccomp_restrict_namespaces(CLONE_NEWNS|CLONE_NEWNET) >= 0);
if (!streq(seccomp, "0"))
log_warning("Warning: seccomp filter detected, results may be unreliable for %s", __func__);
- ASSERT_OK(r = safe_fork("(protect-sysctl)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(protect-sysctl)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
#if defined __NR__sysctl && __NR__sysctl >= 0
assert_se(syscall(__NR__sysctl, NULL) < 0);
/* in containers syslog() is likely missing anyway */
CHECK_SECCOMP(/* skip_container= */ true);
- ASSERT_OK(r = safe_fork("(protect-syslog)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(protect-syslog)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
#if defined __NR_syslog && __NR_syslog >= 0
assert_se(syscall(__NR_syslog, -1, NULL, 0) < 0);
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(restrict-address-families)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(restrict-address-families)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
int fd;
Set *s;
/* in containers RT privs are likely missing anyway */
CHECK_SECCOMP(/* skip_container= */ true);
- ASSERT_OK(r = safe_fork("(restrict-realtime)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(restrict-realtime)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
/* On some CI environments, the restriction may be already enabled. */
if (sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0) {
return;
#endif
- ASSERT_OK(r = safe_fork("(memory_deny_write_execute_mmap)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(memory_deny_write_execute_mmap)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
void *p;
shmid = shmget(IPC_PRIVATE, page_size(), 0);
assert_se(shmid >= 0);
- ASSERT_OK(r = safe_fork("(memory-deny-write-execute)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(memory-deny-write-execute)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
void *p;
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(restrict-archs)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(restrict-archs)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
_cleanup_set_free_ Set *s = NULL;
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(load-filter)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(load-filter)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
_cleanup_hashmap_free_ Hashmap *s = NULL;
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(native-syscalls)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(native-syscalls)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
_cleanup_set_free_ Set *arch_s = NULL;
_cleanup_hashmap_free_ Hashmap *s = NULL;
log_info("current personality=0x%lX", (unsigned long) safe_personality(PERSONALITY_INVALID));
log_info("current opinionated personality=0x%lX", current_opinionated);
- ASSERT_OK(r = safe_fork("(lock-personality)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(lock-personality)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
unsigned long current;
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(suid-sgid)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(suid-sgid)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX";
int fd = -EBADF, k = -EBADF;
CHECK_SECCOMP(/* skip_container= */ false);
- ASSERT_OK(r = safe_fork("(suppress-sync)", FORK_LOG | FORK_WAIT, NULL));
+ r = ASSERT_OK(pidref_safe_fork("(suppress-sync)", FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
test_seccomp_suppress_sync_child();
_exit(EXIT_SUCCESS);
TEST(getpeercred_getpeergroups) {
int r;
- r = safe_fork("(getpeercred)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
- assert_se(r >= 0);
+ r = ASSERT_OK(pidref_safe_fork("(getpeercred)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
static const gid_t gids[] = { 3, 4, 5, 6, 7 };
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
- r = safe_fork("(passfd_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
- assert_se(r >= 0);
+ r = ASSERT_OK(pidref_safe_fork("(passfd_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
/* Child */
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
- r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
- assert_se(r >= 0);
+ r = ASSERT_OK(pidref_safe_fork("(passfd_contents_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
/* Child */
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
- r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
- assert_se(r >= 0);
+ r = ASSERT_OK(pidref_safe_fork("(passfd_contents_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
/* Child */
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
- r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
+ r = ASSERT_OK(pidref_safe_fork("(receive_nopassfd)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
assert_se(r >= 0);
if (r == 0) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
- r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
- assert_se(r >= 0);
+ r = ASSERT_OK(pidref_safe_fork("(send_nodata_nofd)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
/* Child */
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
- r = safe_fork("(send_emptydata)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
- assert_se(r >= 0);
+ r = ASSERT_OK(pidref_safe_fork("(send_emptydata)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL));
if (r == 0) {
/* Child */
ASSERT_OK(pty_fd = openpt_allocate(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK, NULL));
ASSERT_OK(peer_fd = pty_open_peer(pty_fd, O_RDWR|O_NOCTTY|O_CLOEXEC));
- r = safe_fork_full("test-term-session",
- (int[]) { peer_fd, peer_fd, peer_fd },
- NULL, 0,
- FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT|FORK_REARRANGE_STDIO,
- NULL);
+ r = pidref_safe_fork_full(
+ "test-term-session",
+ (int[]) { peer_fd, peer_fd, peer_fd },
+ NULL, 0,
+ FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT|FORK_REARRANGE_STDIO,
+ NULL);
ASSERT_OK(r);
if (r == 0) {
ASSERT_OK(terminal_new_session());
#include "main-func.h"
#include "mkdir-label.h"
#include "path-util.h"
+#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
#include "set.h"
* and its own controlling terminal. If one of the tasks does handle a password, the remaining tasks will be
* terminated.
*/
-static int ask_on_this_console(const char *tty, char **arguments, pid_t *ret_pid) {
+static int ask_on_this_console(const char *tty, char **arguments, PidRef *ret) {
int r;
assert(tty);
assert(arguments);
- assert(ret_pid);
+ assert(ret);
assert_se(sigaction(SIGCHLD, &sigaction_nop_nocldstop, NULL) >= 0);
assert_se(sigaction(SIGHUP, &sigaction_default, NULL) >= 0);
assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGHUP, SIGCHLD) >= 0);
- r = safe_fork("(sd-passwd)", FORK_RESET_SIGNALS|FORK_KEEP_NOTIFY_SOCKET|FORK_LOG, ret_pid);
+ r = pidref_safe_fork("(sd-passwd)", FORK_RESET_SIGNALS|FORK_KEEP_NOTIFY_SOCKET|FORK_LOG, ret);
if (r < 0)
return r;
if (r == 0) {
/* Start an agent on each console. */
STRV_FOREACH(tty, consoles) {
- pid_t pid;
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
- r = ask_on_this_console(*tty, arguments, &pid);
+ r = ask_on_this_console(*tty, arguments, &pidref);
if (r < 0)
return r;
- if (set_put(pids, PID_TO_PTR(pid)) < 0)
+ if (set_put(pids, PID_TO_PTR(pidref.pid)) < 0)
return log_oom();
}
#include "log.h"
#include "mkdir.h"
#include "pidfd-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "set.h"
#include "signal-util.h"
static int start_one_worker(Manager *m) {
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *source = NULL;
bool fixed;
- pid_t pid;
int r;
assert(m);
fixed = set_size(m->workers_fixed) < USERDB_WORKERS_MIN;
- r = safe_fork_full(
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork_full(
"(sd-worker)",
/* stdio_fds= */ NULL,
&m->listen_fd, 1,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_CLOSE_ALL_FDS,
- &pid);
+ &pidref);
if (r < 0)
return log_error_errno(r, "Failed to fork new worker child: %m");
if (r == 0) {
safe_close(m->listen_fd);
}
- r = setenvf("LISTEN_PID", /* overwrite= */ true, PID_FMT, pid);
+ r = setenvf("LISTEN_PID", /* overwrite= */ true, PID_FMT, pidref.pid);
if (r < 0) {
log_error_errno(r, "Failed to set $LISTEN_PID: %m");
_exit(EXIT_FAILURE);
_exit(EXIT_FAILURE);
}
- r = sd_event_add_child(m->event, &source, pid, WEXITED, on_worker_exit, m);
+ r = event_add_child_pidref(m->event, &source, &pidref, WEXITED, on_worker_exit, m);
if (r < 0)
- return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pid);
+ return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pidref.pid);
r = set_ensure_put(
fixed ? &m->workers_fixed : &m->workers_dynamic,
if (!argv)
return log_oom();
- r = safe_fork("(swtpm-setup)", FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL);
+ r = pidref_safe_fork("(swtpm-setup)", FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, /* ret= */ NULL);
if (r == 0) {
/* Child */
execvp(argv[0], argv);
strv_remove(argv, "--profile-name");
strv_remove(argv, "default-v2");
- r = safe_fork("(swtpm-setup)", FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL);
+ r = pidref_safe_fork("(swtpm-setup)", FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, /* ret= */ NULL);
if (r == 0) {
/* Child */
execvp(argv[0], argv);
log_debug("Executing: %s", joined);
}
- r = safe_fork(
+ r = pidref_safe_fork(
ssh_keygen,
FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
- NULL);
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {