From: Daan De Meyer Date: Wed, 19 Nov 2025 13:34:11 +0000 (+0100) Subject: tree-wide: Use pidref_wait_for_terminate_and_check() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbd276cb86a2f0292cc19fd57ee3d72bf73592dc;p=thirdparty%2Fsystemd.git tree-wide: Use pidref_wait_for_terminate_and_check() Let's use the pidref variants for waiting and checking a process everywhere and get rid of the non pidref variants. --- diff --git a/src/basic/lock-util.c b/src/basic/lock-util.c index 4f0bc8b50cb..85c7dc0562f 100644 --- a/src/basic/lock-util.c +++ b/src/basic/lock-util.c @@ -15,6 +15,7 @@ #include "lock-util.h" #include "log.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "string-util.h" #include "time-util.h" @@ -199,7 +200,6 @@ int lock_generic(int fd, LockType type, int operation) { } int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout) { - _cleanup_(sigkill_waitp) pid_t pid = 0; int r; assert(fd >= 0); @@ -223,8 +223,8 @@ int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeo return r; /* If that didn't work, try with a child */ - - r = safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid); + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref); if (r < 0) return log_error_errno(r, "Failed to flock block device in child process: %m"); if (r == 0) { @@ -256,11 +256,11 @@ int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeo } siginfo_t status; - r = wait_for_terminate(pid, &status); + r = pidref_wait_for_terminate(&pidref, &status); if (r < 0) return r; - TAKE_PID(pid); + pidref_done(&pidref); switch (status.si_code) { diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index 3a960e19cc5..555138c2559 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -601,25 +601,25 @@ int userns_acquire_self_root(void) { return userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true); } -int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) { +int userns_enter_and_pin(int userns_fd, PidRef *ret) { _cleanup_close_pair_ int pfd[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; ssize_t n; char x; int r; assert(userns_fd >= 0); - assert(ret_pid); + assert(ret); if (pipe2(pfd, O_CLOEXEC) < 0) return -errno; - r = safe_fork_full( + r = pidref_safe_fork_full( "(sd-pinuserns)", /* stdio_fds= */ NULL, (int[]) { pfd[1], userns_fd }, 2, FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL, - &pid); + &pidref); if (r < 0) return r; if (r == 0) { @@ -652,7 +652,7 @@ int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) { assert(n == 1); assert(x == 'x'); - *ret_pid = TAKE_PID(pid); + *ret = TAKE_PIDREF(pidref); return 0; } @@ -661,22 +661,22 @@ bool userns_supported(void) { } int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) { - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; assert(userns_fd >= 0); - r = userns_enter_and_pin(userns_fd, &pid); + r = userns_enter_and_pin(userns_fd, &pidref); if (r < 0) return r; uid_t uid; - r = uid_map_search_root(pid, UID_RANGE_USERNS_OUTSIDE, &uid); + r = uid_map_search_root(pidref.pid, UID_RANGE_USERNS_OUTSIDE, &uid); if (r < 0) return r; gid_t gid; - r = uid_map_search_root(pid, GID_RANGE_USERNS_OUTSIDE, &gid); + r = uid_map_search_root(pidref.pid, GID_RANGE_USERNS_OUTSIDE, &gid); if (r < 0) return r; diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index 2c4a7da29f1..32e64fa9e68 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -82,7 +82,7 @@ int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_r int userns_acquire_empty(void); int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny); int userns_acquire_self_root(void); -int userns_enter_and_pin(int userns_fd, pid_t *ret_pid); +int userns_enter_and_pin(int userns_fd, PidRef *ret); bool userns_supported(void); int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid); diff --git a/src/basic/pidref.h b/src/basic/pidref.h index d778d49f09a..864acb569df 100644 --- a/src/basic/pidref.h +++ b/src/basic/pidref.h @@ -101,6 +101,15 @@ static inline int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret) { return pidref_wait_for_terminate_full(pidref, USEC_INFINITY, ret); } +static inline void pidref_done_sigterm_wait(PidRef *pidref) { + if (!pidref_is_set(pidref)) + return; + + (void) pidref_kill(pidref, SIGTERM); + (void) pidref_wait_for_terminate(pidref, NULL); + pidref_done(pidref); +} + static inline void pidref_done_sigkill_wait(PidRef *pidref) { if (!pidref_is_set(pidref)) return; diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 94522fb495e..4c59ea4918f 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -845,13 +845,9 @@ int get_process_umask(pid_t pid, mode_t *ret) { return parse_mode(m, ret); } -int wait_for_terminate(pid_t pid, siginfo_t *ret) { - return pidref_wait_for_terminate(&PIDREF_MAKE_FROM_PID(pid), ret); -} - /* * Return values: - * < 0 : wait_for_terminate() failed to get the state of the + * < 0 : pidref_wait_for_terminate() failed to get the state of the * process, the process was terminated by a signal, or * failed for an unknown reason. * >=0 : The process terminated normally, and its exit code is @@ -908,52 +904,6 @@ int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFl return -EPROTO; } -int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) { - return pidref_wait_for_terminate_and_check(name, &PIDREF_MAKE_FROM_PID(pid), flags); -} - -void sigkill_wait(pid_t pid) { - assert(pid > 1); - - (void) kill(pid, SIGKILL); - (void) wait_for_terminate(pid, NULL); -} - -void sigkill_waitp(pid_t *pid) { - PROTECT_ERRNO; - - if (!pid) - return; - if (*pid <= 1) - return; - - sigkill_wait(*pid); -} - -void sigterm_wait(pid_t pid) { - assert(pid > 1); - - (void) kill_and_sigcont(pid, SIGTERM); - (void) wait_for_terminate(pid, NULL); -} - -void sigkill_nowait(pid_t pid) { - assert(pid > 1); - - (void) kill(pid, SIGKILL); -} - -void sigkill_nowaitp(pid_t *pid) { - PROTECT_ERRNO; - - if (!pid) - return; - if (*pid <= 1) - return; - - sigkill_nowait(*pid); -} - int kill_and_sigcont(pid_t pid, int sig) { int r; @@ -1280,7 +1230,9 @@ void valgrind_summary_hack(void) { exit(EXIT_SUCCESS); else { log_info("Spawned valgrind helper as PID "PID_FMT".", pid); - (void) wait_for_terminate(pid, NULL); + _cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid); + (void) pidref_set_pid(&pidref, pid); + (void) pidref_wait_for_terminate(&pidref, NULL); } } #endif diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 4b7641da6ba..24873b448e2 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -60,8 +60,6 @@ static inline bool SIGINFO_CODE_IS_DEAD(int code) { return IN_SET(code, CLD_EXITED, CLD_KILLED, CLD_DUMPED); } -int wait_for_terminate(pid_t pid, siginfo_t *ret); - typedef enum WaitFlags { WAIT_LOG_ABNORMAL = 1 << 0, WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1, @@ -71,13 +69,6 @@ typedef enum WaitFlags { } WaitFlags; int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFlags flags); -int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags); - -void sigkill_wait(pid_t pid); -void sigkill_waitp(pid_t *pid); -void sigterm_wait(pid_t pid); -void sigkill_nowait(pid_t pid); -void sigkill_nowaitp(pid_t *pid); int kill_and_sigcont(pid_t pid, int sig); diff --git a/src/basic/uid-range.c b/src/basic/uid-range.c index 0b87e789abe..81e736ef5af 100644 --- a/src/basic/uid-range.c +++ b/src/basic/uid-range.c @@ -8,6 +8,7 @@ #include "format-util.h" #include "namespace-util.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "sort-util.h" #include "stat-util.h" @@ -286,7 +287,7 @@ int uid_range_load_userns(const char *path, UIDRangeUsernsMode mode, UIDRange ** } int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange **ret) { - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; assert(userns_fd >= 0); @@ -294,12 +295,12 @@ int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange assert(mode < _UID_RANGE_USERNS_MODE_MAX); assert(ret); - r = userns_enter_and_pin(userns_fd, &pid); + r = userns_enter_and_pin(userns_fd, &pidref); if (r < 0) return r; const char *p = procfs_file_alloca( - pid, + pidref.pid, IN_SET(mode, UID_RANGE_USERNS_INSIDE, UID_RANGE_USERNS_OUTSIDE) ? "uid_map" : "gid_map"); return uid_range_load_userns(p, mode, ret); diff --git a/src/core/crash-handler.c b/src/core/crash-handler.c index 495e9efc9b5..b5286c8e69e 100644 --- a/src/core/crash-handler.c +++ b/src/core/crash-handler.c @@ -12,6 +12,7 @@ #include "format-util.h" #include "log.h" #include "main.h" +#include "pidref.h" #include "process-util.h" #include "raw-clone.h" #include "rlimit-util.h" @@ -127,8 +128,11 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) { LOG_MESSAGE_ID(SD_MESSAGE_CRASH_PROCESS_SIGNAL_STR)); } + _cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid); + (void) pidref_set_pid(&pidref, pid); + /* Order things nicely. */ - r = wait_for_terminate(pid, &status); + r = pidref_wait_for_terminate(&pidref, &status); if (r < 0) log_struct_errno(LOG_EMERG, r, LOG_MESSAGE("Caught <%s>, waitpid() failed: %m", signal_to_string(sig)), @@ -181,7 +185,9 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) { _exit(EXIT_EXCEPTION); } else { log_info("Spawned crash shell as PID "PID_FMT".", pid); - (void) wait_for_terminate(pid, NULL); + _cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid); + (void) pidref_set_pid(&pidref, pid); + (void) pidref_wait_for_terminate(&pidref, NULL); } } diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 24e553e1225..01a653f2f1c 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -2406,7 +2406,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi _cleanup_free_ char *uid_map = NULL, *gid_map = NULL; _cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR; _cleanup_close_ int unshare_ready_fd = -EBADF; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; uint64_t c = 1; ssize_t n; int r; @@ -2503,7 +2503,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi if (pipe2(errno_pipe, O_CLOEXEC) < 0) return -errno; - r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid); + r = pidref_safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref); if (r < 0) return r; if (r == 0) { @@ -2535,9 +2535,10 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi if (n != 0) /* on success we should have read 0 bytes */ return -EIO; - r = wait_for_terminate_and_check("(sd-userns)", TAKE_PID(pid), 0); + r = pidref_wait_for_terminate_and_check("(sd-userns)", &pidref, 0); if (r < 0) return r; + pidref_done(&pidref); if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */ return -EIO; @@ -2546,7 +2547,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi static int can_mount_proc(void) { _cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; ssize_t n; int r; @@ -2561,8 +2562,10 @@ static int can_mount_proc(void) { /* Fork a child process into its own mount and PID namespace. Note safe_fork() already remounts / as SLAVE * with FORK_MOUNTNS_SLAVE. */ - r = safe_fork("(sd-proc-check)", - FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_PIDNS, &pid); + r = pidref_safe_fork( + "(sd-proc-check)", + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_PIDNS, + &pidref); if (r < 0) return log_debug_errno(r, "Failed to fork child process (sd-proc-check): %m"); if (r == 0) { @@ -2597,9 +2600,10 @@ static int can_mount_proc(void) { if (n != 0) /* on success we should have read 0 bytes */ return -EIO; - r = wait_for_terminate_and_check("(sd-proc-check)", TAKE_PID(pid), /* flags= */ 0); + r = pidref_wait_for_terminate_and_check("(sd-proc-check)", &pidref, /* flags= */ 0); if (r < 0) return log_debug_errno(r, "Failed to wait for (sd-proc-check) child process to terminate: %m"); + pidref_done(&pidref); if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Child process (sd-proc-check) exited with unexpected exit status '%d'.", r); diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 321e9067f3b..64f7ae99a10 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -42,6 +42,7 @@ #include "parse-argument.h" #include "parse-util.h" #include "path-util.h" +#include "pidref.h" #include "pretty-print.h" #include "process-util.h" #include "signal-util.h" @@ -1177,7 +1178,6 @@ static int run_debug(int argc, char **argv, void *userdata) { bool unlink_path = false; const char *data, *fork_name; size_t len; - pid_t pid; int r; if (!arg_debugger) { @@ -1271,7 +1271,11 @@ static int run_debug(int argc, char **argv, void *userdata) { fork_name = strjoina("(", debugger_call[0], ")"); - r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork( + fork_name, + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, + &pidref); if (r < 0) goto finish; if (r == 0) { @@ -1281,7 +1285,7 @@ static int run_debug(int argc, char **argv, void *userdata) { _exit(EXIT_FAILURE); } - r = wait_for_terminate_and_check(debugger_call[0], pid, WAIT_LOG_ABNORMAL); + r = pidref_wait_for_terminate_and_check(debugger_call[0], &pidref, WAIT_LOG_ABNORMAL); finish: (void) default_signals(SIGINT, SIGTERM); diff --git a/src/delta/delta.c b/src/delta/delta.c index 7eb9d91871c..df28a730a54 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -19,6 +19,7 @@ #include "pager.h" #include "parse-argument.h" #include "path-util.h" +#include "pidref.h" #include "pretty-print.h" #include "process-util.h" #include "stat-util.h" @@ -140,7 +141,6 @@ static int notify_override_unchanged(const char *f) { static int found_override(const char *top, const char *bottom) { _cleanup_free_ char *dest = NULL; - pid_t pid; int r; assert(top); @@ -165,7 +165,11 @@ static int found_override(const char *top, const char *bottom) { fflush(stdout); - r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork( + "(diff)", + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, + &pidref); if (r < 0) return r; if (r == 0) { @@ -175,7 +179,7 @@ static int found_override(const char *top, const char *bottom) { _exit(EXIT_FAILURE); } - (void) wait_for_terminate_and_check("diff", pid, WAIT_LOG_ABNORMAL); + (void) pidref_wait_for_terminate_and_check("diff", &pidref, WAIT_LOG_ABNORMAL); putchar('\n'); return r; diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 6ea5a9f0e7c..9767568724f 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -23,6 +23,7 @@ #include "fsck-util.h" #include "main-func.h" #include "path-util.h" +#include "pidref.h" #include "proc-cmdline.h" #include "process-util.h" #include "socket-util.h" @@ -267,7 +268,6 @@ static int run(int argc, char *argv[]) { bool root_directory; struct stat st; int r, exit_status; - pid_t pid; log_setup(); @@ -366,7 +366,11 @@ static int run(int argc, char *argv[]) { pipe(progress_pipe) < 0) return log_error_errno(errno, "pipe(): %m"); - r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork( + "(fsck)", + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, + &pidref); if (r < 0) return r; if (r == 0) { @@ -424,7 +428,7 @@ static int run(int argc, char *argv[]) { (void) process_progress(TAKE_FD(progress_pipe[0]), console); } - exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL); + exit_status = pidref_wait_for_terminate_and_check("fsck", &pidref, WAIT_LOG_ABNORMAL); if (exit_status < 0) return exit_status; if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) { diff --git a/src/home/homectl.c b/src/home/homectl.c index 8d8f2c0f121..ce45ec30c4a 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -46,6 +46,7 @@ #include "password-quality-util.h" #include "path-util.h" #include "percent-util.h" +#include "pidref.h" #include "pkcs11-util.h" #include "polkit-agent.h" #include "pretty-print.h" @@ -2341,7 +2342,6 @@ static int with_home(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **cmdline = NULL; const char *home; int r, ret; - pid_t pid; r = acquire_bus(&bus); if (r < 0) @@ -2414,7 +2414,11 @@ static int with_home(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_parse_error(r); - r = safe_fork("(with)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork( + "(with)", + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG, + &pidref); if (r < 0) return r; if (r == 0) { @@ -2428,7 +2432,7 @@ static int with_home(int argc, char *argv[], void *userdata) { _exit(255); } - ret = wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL); + ret = pidref_wait_for_terminate_and_check(cmdline[0], &pidref, WAIT_LOG_ABNORMAL); /* Close the fd that pings the home now. */ acquired_fd = safe_close(acquired_fd); diff --git a/src/home/homework-cifs.c b/src/home/homework-cifs.c index a34f0754999..23d5abb019b 100644 --- a/src/home/homework-cifs.c +++ b/src/home/homework-cifs.c @@ -15,6 +15,7 @@ #include "memfd-util.h" #include "mount-util.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "stat-util.h" #include "string-util.h" @@ -75,14 +76,17 @@ int home_setup_cifs( STRV_FOREACH(pw, h->password) { _cleanup_close_ int passwd_fd = -EBADF; - pid_t mount_pid; int exit_status; passwd_fd = memfd_new_and_seal_string("cifspw", *pw); if (passwd_fd < 0) return log_error_errno(passwd_fd, "Failed to create data FD for password: %m"); - r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid); + _cleanup_(pidref_done) PidRef mount_pidref = PIDREF_NULL; + r = pidref_safe_fork( + "(mount)", + FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR, + &mount_pidref); if (r < 0) return r; if (r == 0) { @@ -108,7 +112,7 @@ int home_setup_cifs( _exit(EXIT_FAILURE); } - exit_status = wait_for_terminate_and_check("mount", mount_pid, WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS); + exit_status = pidref_wait_for_terminate_and_check("mount", &mount_pidref, WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS); if (exit_status < 0) return exit_status; if (exit_status == EXIT_SUCCESS) { diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 316afb6f5ec..8ed45554511 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -7,6 +7,7 @@ #include #include #include +#include "pidref.h" #if HAVE_VALGRIND_MEMCHECK_H #include #endif @@ -227,7 +228,6 @@ static int block_get_size_by_path(const char *path, uint64_t *ret) { static int run_fsck(const char *node, const char *fstype) { int r, exit_status; - pid_t fsck_pid; assert(node); assert(fstype); @@ -240,9 +240,11 @@ static int run_fsck(const char *node, const char *fstype) { return 0; } - r = safe_fork("(fsck)", - FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, - &fsck_pid); + _cleanup_(pidref_done) PidRef fsck_pidref = PIDREF_NULL; + r = pidref_safe_fork( + "(fsck)", + FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, + &fsck_pidref); if (r < 0) return r; if (r == 0) { @@ -253,7 +255,7 @@ static int run_fsck(const char *node, const char *fstype) { _exit(FSCK_OPERATIONAL_ERROR); } - exit_status = wait_for_terminate_and_check("fsck", fsck_pid, WAIT_LOG_ABNORMAL); + exit_status = pidref_wait_for_terminate_and_check("fsck", &fsck_pidref, WAIT_LOG_ABNORMAL); if (exit_status < 0) return exit_status; if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) { @@ -2604,7 +2606,7 @@ static int ext4_offline_resize_fs( _cleanup_free_ char *size_str = NULL; bool re_open = false, re_mount = false; - pid_t resize_pid, fsck_pid; + _cleanup_(pidref_done) PidRef resize_pidref = PIDREF_NULL, fsck_pidref = PIDREF_NULL; int r, exit_status; assert(setup); @@ -2627,9 +2629,10 @@ static int ext4_offline_resize_fs( log_info("Temporary unmounting of file system completed."); /* resize2fs requires that the file system is force checked first, do so. */ - r = safe_fork("(e2fsck)", - FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, - &fsck_pid); + r = pidref_safe_fork( + "(e2fsck)", + FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, + &fsck_pidref); if (r < 0) return r; if (r == 0) { @@ -2640,7 +2643,7 @@ static int ext4_offline_resize_fs( _exit(EXIT_FAILURE); } - exit_status = wait_for_terminate_and_check("e2fsck", fsck_pid, WAIT_LOG_ABNORMAL); + exit_status = pidref_wait_for_terminate_and_check("e2fsck", &fsck_pidref, WAIT_LOG_ABNORMAL); if (exit_status < 0) return exit_status; if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) { @@ -2659,9 +2662,10 @@ static int ext4_offline_resize_fs( return log_oom(); /* Resize the thing */ - r = safe_fork("(e2resize)", - FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, - &resize_pid); + r = pidref_safe_fork( + "(e2resize)", + FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, + &resize_pidref); if (r < 0) return r; if (r == 0) { diff --git a/src/import/pull-common.c b/src/import/pull-common.c index 4154487fd57..cc06fe4f1db 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -12,6 +12,7 @@ #include "memory-util.h" #include "os-util.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "pull-common.h" #include "pull-job.h" @@ -404,7 +405,7 @@ static int verify_gpg( _cleanup_close_pair_ int gpg_pipe[2] = EBADF_PAIR; _cleanup_(rm_rf_physical_and_freep) char *gpg_home = NULL; char sig_file_path[] = "/tmp/sigXXXXXX"; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; assert(iovec_is_valid(payload)); @@ -434,11 +435,12 @@ static int verify_gpg( goto finish; } - r = safe_fork_full("(gpg)", - (int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO }, - NULL, 0, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, - &pid); + r = pidref_safe_fork_full( + "(gpg)", + (int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO }, + /* except_fds= */ NULL, /* n_except_fds= */ 0, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, + &pidref); if (r < 0) return r; if (r == 0) { @@ -497,9 +499,10 @@ static int verify_gpg( gpg_pipe[1] = safe_close(gpg_pipe[1]); - r = wait_for_terminate_and_check("gpg", TAKE_PID(pid), WAIT_LOG_ABNORMAL); + r = pidref_wait_for_terminate_and_check("gpg", &pidref, WAIT_LOG_ABNORMAL); if (r < 0) goto finish; + pidref_done(&pidref); if (r != EXIT_SUCCESS) r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "DOWNLOAD INVALID: Signature verification failed."); diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 177f88c2c7a..999e62f0081 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -8,6 +8,7 @@ #include "bus-match.h" #include "constants.h" #include "list.h" +#include "pidref.h" #include "runtime-scope.h" #include "socket-util.h" @@ -271,7 +272,7 @@ typedef struct sd_bus { unsigned n_memfd_cache; uint64_t origin_id; - pid_t busexec_pid; + PidRef busexec_pidref; unsigned iteration_counter; diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 5f8d015569d..32eda5627e7 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -1163,7 +1163,7 @@ int bus_socket_exec(sd_bus *b) { assert(b->input_fd < 0); assert(b->output_fd < 0); assert(b->exec_path); - assert(b->busexec_pid == 0); + assert(!pidref_is_set(&b->busexec_pidref)); if (DEBUG_LOGGING) { _cleanup_free_ char *line = NULL; @@ -1181,10 +1181,12 @@ int bus_socket_exec(sd_bus *b) { if (r < 0) return -errno; - r = safe_fork_full("(sd-busexec)", - (int[]) { s[1], s[1], STDERR_FILENO }, - NULL, 0, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid); + r = pidref_safe_fork_full( + "(sd-busexec)", + (int[]) { s[1], s[1], STDERR_FILENO }, + NULL, 0, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE, + &b->busexec_pidref); if (r < 0) { safe_close_pair(s); return r; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index eecde50d741..8318bc58537 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -41,7 +41,6 @@ #include "parse-util.h" #include "path-util.h" #include "prioq.h" -#include "process-util.h" #include "set.h" #include "string-util.h" #include "strv.h" @@ -262,6 +261,7 @@ _public_ int sd_bus_new(sd_bus **ret) { .creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME, .accept_fd = true, .origin_id = origin_id_query(), + .busexec_pidref = PIDREF_NULL, .n_groups = SIZE_MAX, .close_on_exit = true, .ucred = UCRED_INVALID, @@ -1121,13 +1121,6 @@ static int bus_parse_next_address(sd_bus *b) { return 1; } -static void bus_kill_exec(sd_bus *bus) { - if (!pid_is_valid(bus->busexec_pid)) - return; - - sigterm_wait(TAKE_PID(bus->busexec_pid)); -} - static int bus_start_address(sd_bus *b) { int r; @@ -1136,7 +1129,7 @@ static int bus_start_address(sd_bus *b) { for (;;) { bus_close_fds(b); - bus_kill_exec(b); + pidref_done_sigterm_wait(&b->busexec_pidref); /* If you provide multiple different bus-addresses, we * try all of them in order and use the first one that @@ -1778,7 +1771,7 @@ _public_ void sd_bus_close(sd_bus *bus) { return; /* Don't leave ssh hanging around */ - bus_kill_exec(bus); + pidref_done_sigterm_wait(&bus->busexec_pidref); bus_set_state(bus, BUS_CLOSED); @@ -1809,7 +1802,7 @@ _public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) { return NULL; /* Have to do this before flush() to prevent hang */ - bus_kill_exec(bus); + pidref_done_sigterm_wait(&bus->busexec_pidref); sd_bus_flush(bus); return sd_bus_close_unref(bus); diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c index b7b5052a930..4532d2335c1 100644 --- a/src/libsystemd/sd-varlink/sd-varlink.c +++ b/src/libsystemd/sd-varlink/sd-varlink.c @@ -26,6 +26,7 @@ #include "mkdir.h" #include "path-util.h" #include "pidfd-util.h" +#include "pidref.h" #include "process-util.h" #include "socket-util.h" #include "string-table.h" @@ -149,6 +150,8 @@ static int varlink_new(sd_varlink **ret) { .allow_fd_passing_input = -1, .af = -1, + + .exec_pidref = PIDREF_NULL, }; *ret = v; @@ -209,7 +212,7 @@ _public_ int sd_varlink_connect_address(sd_varlink **ret, const char *address) { _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, char **_argv) { _cleanup_close_pair_ int pair[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; _cleanup_free_ char *command = NULL; _cleanup_strv_free_ char **argv = NULL; int r; @@ -239,13 +242,13 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha if (r < 0) return log_debug_errno(r, "Failed to disable O_NONBLOCK for varlink socket: %m"); - r = safe_fork_full( + r = pidref_safe_fork_full( "(sd-vlexec)", /* stdio_fds= */ NULL, /* except_fds= */ (int[]) { pair[1] }, /* n_except_fds= */ 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, - &pid); + &pidref); if (r < 0) return log_debug_errno(r, "Failed to spawn process: %m"); if (r == 0) { @@ -266,7 +269,7 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha _exit(EXIT_FAILURE); } - xsprintf(spid, PID_FMT, pid); + xsprintf(spid, PID_FMT, pidref.pid); uint64_t pidfdid; if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) { @@ -298,7 +301,7 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha v->output_fd = v->input_fd = TAKE_FD(pair[0]); v->af = AF_UNIX; - v->exec_pid = TAKE_PID(pid); + v->exec_pidref = TAKE_PIDREF(pidref); varlink_set_state(v, VARLINK_IDLE_CLIENT); *ret = v; @@ -318,7 +321,7 @@ static int ssh_path(const char **ret) { static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) { _cleanup_close_pair_ int pair[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; assert_return(ret, -EINVAL); @@ -356,13 +359,13 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) { if (socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, pair) < 0) return log_debug_errno(errno, "Failed to allocate AF_UNIX socket pair: %m"); - r = safe_fork_full( + r = pidref_safe_fork_full( "(sd-vlssh)", /* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO }, /* except_fds= */ NULL, /* n_except_fds= */ 0, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO, - &pid); + &pidref); if (r < 0) return log_debug_errno(r, "Failed to spawn process: %m"); if (r == 0) { @@ -382,7 +385,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) { v->output_fd = v->input_fd = TAKE_FD(pair[0]); v->af = AF_UNIX; - v->exec_pid = TAKE_PID(pid); + v->exec_pidref = TAKE_PIDREF(pidref); varlink_set_state(v, VARLINK_IDLE_CLIENT); *ret = v; @@ -391,7 +394,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) { static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) { _cleanup_close_pair_ int input_pipe[2] = EBADF_PAIR, output_pipe[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; assert_return(ret, -EINVAL); @@ -440,13 +443,13 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) { if (pipe2(output_pipe, O_CLOEXEC) < 0) return log_debug_errno(errno, "Failed to allocate output pipe: %m"); - r = safe_fork_full( + r = pidref_safe_fork_full( "(sd-vlssh)", /* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO }, /* except_fds= */ NULL, /* n_except_fds= */ 0, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO, - &pid); + &pidref); if (r < 0) return log_debug_errno(r, "Failed to spawn process: %m"); if (r == 0) { @@ -475,7 +478,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) { v->input_fd = TAKE_FD(output_pipe[0]); v->output_fd = TAKE_FD(input_pipe[1]); v->af = AF_UNSPEC; - v->exec_pid = TAKE_PID(pid); + v->exec_pidref = TAKE_PIDREF(pidref); varlink_set_state(v, VARLINK_IDLE_CLIENT); *ret = v; @@ -648,10 +651,7 @@ static void varlink_clear(sd_varlink *v) { v->event = sd_event_unref(v->event); - if (v->exec_pid > 0) { - sigterm_wait(v->exec_pid); - v->exec_pid = 0; - } + pidref_done_sigterm_wait(&v->exec_pidref); v->peer_pidfd = safe_close(v->peer_pidfd); } diff --git a/src/libsystemd/sd-varlink/varlink-internal.h b/src/libsystemd/sd-varlink/varlink-internal.h index 8041a30a5ea..a2c54a0bf5a 100644 --- a/src/libsystemd/sd-varlink/varlink-internal.h +++ b/src/libsystemd/sd-varlink/varlink-internal.h @@ -6,6 +6,7 @@ #include "sd-varlink.h" #include "list.h" +#include "pidref.h" #include "sd-forward.h" typedef enum VarlinkState { @@ -187,7 +188,7 @@ struct sd_varlink { sd_event_source *quit_event_source; sd_event_source *defer_event_source; - pid_t exec_pid; + PidRef exec_pidref; }; typedef struct VarlinkServerSocket VarlinkServerSocket; diff --git a/src/login/inhibit.c b/src/login/inhibit.c index 51379edc37e..786594c9ee3 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -20,6 +20,7 @@ #include "main-func.h" #include "pager.h" #include "parse-argument.h" +#include "pidref.h" #include "polkit-agent.h" #include "pretty-print.h" #include "process-util.h" @@ -330,7 +331,6 @@ static int run(int argc, char *argv[]) { _cleanup_strv_free_ char **arguments = NULL; _cleanup_free_ char *w = NULL; _cleanup_close_ int fd = -EBADF; - pid_t pid; /* Ignore SIGINT and allow the forked process to receive it */ (void) ignore_signals(SIGINT); @@ -360,7 +360,8 @@ static int run(int argc, char *argv[]) { if (!arguments) return log_oom(); - r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref); if (r < 0) return r; if (r == 0) { @@ -371,7 +372,7 @@ static int run(int argc, char *argv[]) { _exit(EXIT_FAILURE); } - return wait_for_terminate_and_check(argv[optind], pid, WAIT_LOG); + return pidref_wait_for_terminate_and_check(argv[optind], &pidref, WAIT_LOG); } } diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index f7e3f7f93c5..9579ae0c12a 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -32,7 +32,7 @@ int bus_image_method_remove( _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR; Image *image = ASSERT_PTR(userdata); Manager *m = image->userdata; - pid_t child; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; int r; assert(message); @@ -62,7 +62,7 @@ int bus_image_method_remove( if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); - r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); + r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); if (r == 0) { @@ -73,11 +73,11 @@ int bus_image_method_remove( errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); - r = operation_new_with_bus_reply(m, /* machine= */ NULL, child, message, errno_pipe_fd[0], /* ret= */ NULL); - if (r < 0) { - sigkill_wait(child); + r = operation_new_with_bus_reply(m, /* machine= */ NULL, &child, message, errno_pipe_fd[0], /* ret= */ NULL); + if (r < 0) return r; - } + + TAKE_PIDREF(child); errno_pipe_fd[0] = -EBADF; @@ -140,7 +140,7 @@ int bus_image_method_clone( Manager *m = ASSERT_PTR(image->userdata); const char *new_name; int r, read_only; - pid_t child; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; assert(message); @@ -177,7 +177,7 @@ int bus_image_method_clone( if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); - r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child); + r = pidref_safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); if (r == 0) { @@ -188,11 +188,11 @@ int bus_image_method_clone( errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); - r = operation_new_with_bus_reply(m, /* machine= */ NULL, child, message, errno_pipe_fd[0], /* ret= */ NULL); - if (r < 0) { - sigkill_wait(child); + r = operation_new_with_bus_reply(m, /* machine= */ NULL, &child, message, errno_pipe_fd[0], /* ret= */ NULL); + if (r < 0) return r; - } + + TAKE_PIDREF(child); errno_pipe_fd[0] = -EBADF; diff --git a/src/machine/image-varlink.c b/src/machine/image-varlink.c index 908952dcf57..bf9826c6812 100644 --- a/src/machine/image-varlink.c +++ b/src/machine/image-varlink.c @@ -115,7 +115,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR; ImageUpdateParameters p = IMAGE_UPDATE_PARAMETERS_NULL; Image *image; - pid_t child; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; int r; assert(link); @@ -156,7 +156,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) return log_debug_errno(errno, "Failed to open pipe: %m"); - r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child); + r = pidref_safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child); if (r < 0) return log_debug_errno(r, "Failed to fork: %m"); if (r == 0) { @@ -167,12 +167,11 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); - r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, child, link, errno_pipe_fd[0], /* ret= */ NULL); - if (r < 0) { - sigkill_wait(child); + r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, &child, link, errno_pipe_fd[0], /* ret= */ NULL); + if (r < 0) return r; - } + TAKE_PIDREF(child); TAKE_FD(errno_pipe_fd[0]); return 1; } @@ -188,7 +187,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR; const char *image_name; Image *image; - pid_t child; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; int r; assert(link); @@ -225,7 +224,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) return log_debug_errno(errno, "Failed to open pipe: %m"); - r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); + r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); if (r < 0) return log_debug_errno(r, "Failed to fork: %m"); if (r == 0) { @@ -236,12 +235,11 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); - r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, child, link, errno_pipe_fd[0], /* ret= */ NULL); - if (r < 0) { - sigkill_wait(child); + r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, &child, link, errno_pipe_fd[0], /* ret= */ NULL); + if (r < 0) return r; - } + TAKE_PIDREF(child); TAKE_FD(errno_pipe_fd[0]); return 1; } diff --git a/src/machine/image.c b/src/machine/image.c index 0abee746db6..c1ad25668a0 100644 --- a/src/machine/image.c +++ b/src/machine/image.c @@ -96,7 +96,7 @@ int clean_pool_read_next_entry(FILE *file, char **ret_name, uint64_t *ret_usage) int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operation **ret_operation) { _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR; _cleanup_close_ int result_fd = -EBADF; - _cleanup_(sigkill_waitp) pid_t child = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; int r; assert(manager); @@ -113,7 +113,7 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat return log_debug_errno(result_fd, "Failed to open tmpfile: %m"); /* This might be a slow operation, run it asynchronously in a background process */ - r = safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child); + r = pidref_safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child); if (r < 0) return log_debug_errno(r, "Failed to fork(): %m"); if (r == 0) { @@ -183,13 +183,13 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); /* The clean-up might take a while, hence install a watch on the child and return */ - r = operation_new(manager, /* machine= */ NULL, child, errno_pipe_fd[0], ret_operation); + r = operation_new(manager, /* machine= */ NULL, &child, errno_pipe_fd[0], ret_operation); if (r < 0) return r; (*ret_operation)->extra_fd = TAKE_FD(result_fd); TAKE_FD(errno_pipe_fd[0]); - TAKE_PID(child); + TAKE_PIDREF(child); return 0; } diff --git a/src/machine/machine.c b/src/machine/machine.c index 1176649388a..6914b912ce9 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -1244,7 +1244,7 @@ int machine_copy_from_to_operation( // TODO: port to PidRef and donate child rather than destroying it Operation *operation; - r = operation_new(manager, machine, child.pid, errno_pipe_fd[0], &operation); + r = operation_new(manager, machine, &child, errno_pipe_fd[0], &operation); if (r < 0) return r; diff --git a/src/machine/operation.c b/src/machine/operation.c index 8c43cc200f3..0e8fd3a5d8b 100644 --- a/src/machine/operation.c +++ b/src/machine/operation.c @@ -8,6 +8,7 @@ #include "sd-varlink.h" #include "alloc-util.h" +#include "event-util.h" #include "fd-util.h" #include "format-util.h" #include "log.h" @@ -45,10 +46,10 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat assert(si); log_debug("Operation " PID_FMT " is now complete with code=%s status=%i", - o->pid, + o->pidref.pid, sigchld_code_to_string(si->si_code), si->si_status); - o->pid = 0; + pidref_done(&o->pidref); r = read_operation_errno(si, o); if (r < 0) @@ -96,12 +97,12 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat return 0; } -int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, Operation **ret) { +int operation_new(Manager *manager, Machine *machine, PidRef *child, int errno_fd, Operation **ret) { Operation *o; int r; assert(manager); - assert(child > 1); + assert(pidref_is_set(child)); assert(errno_fd >= 0); assert(ret); @@ -110,12 +111,12 @@ int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, return -ENOMEM; *o = (Operation) { - .pid = child, + .pidref = TAKE_PIDREF(*child), .errno_fd = errno_fd, .extra_fd = -EBADF }; - r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o); + r = event_add_child_pidref(manager->event, &o->event_source, &o->pidref, WEXITED, operation_done, o); if (r < 0) { free(o); return r; @@ -130,7 +131,7 @@ int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, o->machine = machine; } - log_debug("Started new operation " PID_FMT ".", child); + log_debug("Started new operation " PID_FMT ".", o->pidref.pid); /* At this point we took ownership of both the child and the errno file descriptor! */ @@ -147,8 +148,7 @@ Operation *operation_free(Operation *o) { safe_close(o->errno_fd); safe_close(o->extra_fd); - if (o->pid > 1) - sigkill_wait(o->pid); + pidref_done_sigkill_wait(&o->pidref); sd_bus_message_unref(o->message); sd_varlink_unref(o->link); diff --git a/src/machine/operation.h b/src/machine/operation.h index 2425694aff1..db9c8dfbda4 100644 --- a/src/machine/operation.h +++ b/src/machine/operation.h @@ -3,13 +3,14 @@ #include "list.h" #include "machine-forward.h" +#include "pidref.h" #define OPERATIONS_MAX 64 typedef struct Operation { Manager *manager; Machine *machine; - pid_t pid; + PidRef pidref; /* only one of these two fields should be set */ sd_varlink *link; @@ -23,7 +24,7 @@ typedef struct Operation { LIST_FIELDS(Operation, operations_by_machine); } Operation; -int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, Operation **ret); +int operation_new(Manager *manager, Machine *machine, PidRef *child, int errno_fd, Operation **ret); Operation *operation_free(Operation *o); void operation_attach_bus_reply(Operation *op, sd_bus_message *message); @@ -32,7 +33,7 @@ void operation_attach_varlink_reply(Operation *op, sd_varlink *link); static inline int operation_new_with_bus_reply( Manager *manager, Machine *machine, - pid_t child, + PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret) { @@ -55,7 +56,7 @@ static inline int operation_new_with_bus_reply( static inline int operation_new_with_varlink_reply( Manager *manager, Machine *machine, - pid_t child, + PidRef *child, sd_varlink *link, int errno_fd, Operation **ret) { diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c index 342a9b9212e..1c167ebc029 100644 --- a/src/nspawn/nspawn-setuid.c +++ b/src/nspawn/nspawn-setuid.c @@ -11,26 +11,28 @@ #include "log.h" #include "mkdir.h" #include "nspawn-setuid.h" +#include "pidref.h" #include "process-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" -static int spawn_getent(const char *database, const char *key, pid_t *rpid) { +static int spawn_getent(const char *database, const char *key, PidRef *ret) { int pipe_fds[2], r; - pid_t pid; assert(database); assert(key); - assert(rpid); + assert(ret); if (pipe2(pipe_fds, O_CLOEXEC) < 0) return log_error_errno(errno, "Failed to allocate pipe: %m"); - r = safe_fork_full("(getent)", - (int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, - &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork_full( + "(getent)", + (int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, + &pidref); if (r < 0) { safe_close_pair(pipe_fds); return r; @@ -43,7 +45,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) { pipe_fds[1] = safe_close(pipe_fds[1]); - *rpid = pid; + *ret = TAKE_PIDREF(pidref); return pipe_fds[0]; } @@ -84,7 +86,6 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) { unsigned n_gids = 0; uid_t uid; gid_t gid; - pid_t pid; int r; assert(ret_home); @@ -101,7 +102,8 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) { } /* First, get user credentials */ - fd = spawn_getent("passwd", user, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + fd = spawn_getent("passwd", user, &pidref); if (fd < 0) return fd; @@ -116,7 +118,7 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) { if (r < 0) return log_error_errno(r, "Failed to read from getent: %m"); - (void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG); + (void) pidref_wait_for_terminate_and_check("getent passwd", &pidref, WAIT_LOG); x = strchr(line, ':'); if (!x) @@ -173,7 +175,8 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) { line = mfree(line); /* Second, get group memberships */ - fd = spawn_getent("initgroups", user, &pid); + pidref_done(&pidref); + fd = spawn_getent("initgroups", user, &pidref); if (fd < 0) return fd; @@ -188,7 +191,7 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) { if (r < 0) return log_error_errno(r, "Failed to read from getent: %m"); - (void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG); + (void) pidref_wait_for_terminate_and_check("getent initgroups", &pidref, WAIT_LOG); /* Skip over the username and subsequent separator whitespace */ x = line; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index e4fccaa3a78..bb90cc1c940 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2884,7 +2884,7 @@ static int recursive_chown(const char *directory, uid_t shift, uid_t range) { /* * Return values: - * < 0 : wait_for_terminate() failed to get the state of the + * < 0 : pidref_wait_for_terminate() failed to get the state of the * container, the container was terminated by a signal, or * failed for an unknown reason. No change is made to the * container argument. diff --git a/src/nsresourced/nsresourcework.c b/src/nsresourced/nsresourcework.c index 15aaca61fc2..7004d03c482 100644 --- a/src/nsresourced/nsresourcework.c +++ b/src/nsresourced/nsresourcework.c @@ -541,7 +541,7 @@ static int allocate_now( } static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) { - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; _cleanup_close_ int efd = -EBADF; uint64_t u; int r; @@ -560,7 +560,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) { if (efd < 0) return log_error_errno(errno, "Failed to allocate eventfd(): %m"); - r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pid); + r = pidref_safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref); if (r < 0) return r; if (r == 0) { @@ -590,7 +590,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) { _cleanup_free_ char *pmap = NULL; - if (asprintf(&pmap, "/proc/" PID_FMT "/uid_map", pid) < 0) + if (asprintf(&pmap, "/proc/" PID_FMT "/uid_map", pidref.pid) < 0) return log_oom(); r = write_string_filef(pmap, 0, UID_FMT " " UID_FMT " %" PRIu32 "\n", userns_info->target_uid, userns_info->start_uid, userns_info->size); @@ -598,7 +598,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) { return log_error_errno(r, "Failed to write 'uid_map' file of user namespace: %m"); pmap = mfree(pmap); - if (asprintf(&pmap, "/proc/" PID_FMT "/gid_map", pid) < 0) + if (asprintf(&pmap, "/proc/" PID_FMT "/gid_map", pidref.pid) < 0) return log_oom(); r = write_string_filef(pmap, 0, GID_FMT " " GID_FMT " %" PRIu32 "\n", userns_info->target_gid, userns_info->start_gid, userns_info->size); diff --git a/src/nsresourced/test-userns-restrict.c b/src/nsresourced/test-userns-restrict.c index 68ac3e47220..b40c6551bca 100644 --- a/src/nsresourced/test-userns-restrict.c +++ b/src/nsresourced/test-userns-restrict.c @@ -11,6 +11,7 @@ #include "log.h" #include "main-func.h" #include "namespace-util.h" +#include "pidref.h" #include "process-util.h" #include "rm-rf.h" #include "tmpfile-util.h" @@ -56,7 +57,7 @@ static int run(int argc, char *argv[]) { _cleanup_(userns_restrict_bpf_freep) struct userns_restrict_bpf *obj = NULL; _cleanup_close_ int userns_fd = -EBADF, host_fd1 = -EBADF, host_tmpfs = -EBADF, afd = -EBADF, bfd = -EBADF; _cleanup_(rm_rf_physical_and_freep) char *t = NULL; - _cleanup_(sigkill_waitp) pid_t pid = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; log_set_max_level(LOG_DEBUG); @@ -100,7 +101,7 @@ static int run(int argc, char *argv[]) { assert_se(afd >= 0 && bfd >= 0); - r = safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pid); + r = pidref_safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pidref); assert_se(r >= 0); if (r == 0) { _cleanup_close_ int private_tmpfs = -EBADF; @@ -178,7 +179,7 @@ static int run(int argc, char *argv[]) { assert_se(eventfd_write(bfd, 1) >= 0); - assert_se(wait_for_terminate_and_check("(test)", pid, WAIT_LOG) >= 0); + assert_se(pidref_wait_for_terminate_and_check("(test)", &pidref, WAIT_LOG) >= 0); return 0; } diff --git a/src/portable/portable.c b/src/portable/portable.c index c30fac53fe1..c3fdf5d5afb 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -36,13 +36,13 @@ #include "mkdir.h" #include "os-util.h" #include "path-lookup.h" +#include "pidref.h" #include "portable.h" #include "portable-util.h" #include "process-util.h" #include "rm-rf.h" #include "selinux-util.h" #include "set.h" -#include "signal-util.h" #include "socket-util.h" #include "sort-util.h" #include "string-table.h" @@ -400,7 +400,7 @@ static int portable_extract_by_path( _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; _cleanup_(rmdir_and_freep) char *tmpdir = NULL; _cleanup_close_pair_ int seq[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t child = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; DissectImageFlags flags = DISSECT_IMAGE_READ_ONLY | DISSECT_IMAGE_GENERIC_ROOT | @@ -420,8 +420,6 @@ static int portable_extract_by_path( /* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it * there, and extract the metadata we need. The metadata is sent from the child back to us. */ - BLOCK_SIGNALS(SIGCHLD); - /* Load some libraries before we fork workers off that want to use them */ (void) dlopen_cryptsetup(); (void) dlopen_libmount(); @@ -454,7 +452,7 @@ static int portable_extract_by_path( if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0) return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m"); - r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child); + r = pidref_safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child); if (r < 0) return r; if (r == 0) { @@ -540,10 +538,11 @@ static int portable_extract_by_path( assert_not_reached(); } - r = wait_for_terminate_and_check("(sd-dissect)", child, 0); + r = pidref_wait_for_terminate_and_check("(sd-dissect)", &child, 0); if (r < 0) return r; - child = 0; + + TAKE_PIDREF(child); } if (!os_release) diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c index 21d7bab262c..3dbc094a217 100644 --- a/src/portable/portabled-image-bus.c +++ b/src/portable/portabled-image-bus.c @@ -488,7 +488,7 @@ int bus_image_common_remove( sd_bus_error *error) { _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t child = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; PortableState state; int r; @@ -533,7 +533,7 @@ int bus_image_common_remove( if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); - r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); + r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); if (r == 0) { @@ -550,11 +550,11 @@ int bus_image_common_remove( errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); - r = operation_new(m, child, message, errno_pipe_fd[0], NULL); + r = operation_new(m, &child, message, errno_pipe_fd[0], NULL); if (r < 0) return r; - child = 0; + TAKE_PIDREF(child); errno_pipe_fd[0] = -EBADF; return 1; diff --git a/src/portable/portabled-operation.c b/src/portable/portabled-operation.c index c0039957dc2..99d933a6322 100644 --- a/src/portable/portabled-operation.c +++ b/src/portable/portabled-operation.c @@ -7,6 +7,7 @@ #include "sd-event.h" #include "alloc-util.h" +#include "event-util.h" #include "fd-util.h" #include "format-util.h" #include "log.h" @@ -22,10 +23,10 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat assert(si); log_debug("Operation " PID_FMT " is now complete with code=%s status=%i", - o->pid, + o->pidref.pid, sigchld_code_to_string(si->si_code), si->si_status); - o->pid = 0; + pidref_done(&o->pidref); if (si->si_code != CLD_EXITED) { r = sd_bus_error_set(&error, SD_BUS_ERROR_FAILED, "Child died abnormally."); @@ -74,12 +75,12 @@ fail: return 0; } -int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) { +int operation_new(Manager *manager, PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret) { Operation *o; int r; assert(manager); - assert(child > 1); + assert(pidref_is_set(child)); assert(message); assert(errno_fd >= 0); @@ -89,13 +90,13 @@ int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int er o->extra_fd = -EBADF; - r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o); + r = event_add_child_pidref(manager->event, &o->event_source, child, WEXITED, operation_done, o); if (r < 0) { free(o); return r; } - o->pid = child; + o->pidref = TAKE_PIDREF(*child); o->message = sd_bus_message_ref(message); o->errno_fd = errno_fd; @@ -103,7 +104,7 @@ int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int er manager->n_operations++; o->manager = manager; - log_debug("Started new operation " PID_FMT ".", child); + log_debug("Started new operation " PID_FMT ".", o->pidref.pid); /* At this point we took ownership of both the child and the errno file descriptor! */ @@ -122,8 +123,7 @@ Operation *operation_free(Operation *o) { safe_close(o->errno_fd); safe_close(o->extra_fd); - if (o->pid > 1) - sigkill_wait(o->pid); + pidref_done_sigkill_wait(&o->pidref); sd_bus_message_unref(o->message); diff --git a/src/portable/portabled-operation.h b/src/portable/portabled-operation.h index 7d3210a3f35..7e46264a04a 100644 --- a/src/portable/portabled-operation.h +++ b/src/portable/portabled-operation.h @@ -2,13 +2,14 @@ #pragma once #include "list.h" +#include "pidref.h" #include "portabled-forward.h" #define OPERATIONS_MAX 64 typedef struct Operation { Manager *manager; - pid_t pid; + PidRef pidref; sd_bus_message *message; int errno_fd; int extra_fd; @@ -17,5 +18,5 @@ typedef struct Operation { LIST_FIELDS(Operation, operations); } Operation; -int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret); +int operation_new(Manager *manager, PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret); Operation *operation_free(Operation *o); diff --git a/src/shared/ask-password-agent.c b/src/shared/ask-password-agent.c index 015d413506c..438fda7c45d 100644 --- a/src/shared/ask-password-agent.c +++ b/src/shared/ask-password-agent.c @@ -1,19 +1,17 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include - #include "ask-password-agent.h" #include "bus-util.h" #include "exec-util.h" #include "log.h" -#include "process-util.h" +#include "pidref.h" -static pid_t agent_pid = 0; +static PidRef agent_pidref = PIDREF_NULL; int ask_password_agent_open(void) { int r; - if (agent_pid > 0) + if (pidref_is_set(&agent_pidref)) return 0; r = shall_fork_agent(); @@ -22,7 +20,7 @@ int ask_password_agent_open(void) { r = fork_agent("(sd-askpwagent)", NULL, 0, - &agent_pid, + &agent_pidref, SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch"); if (r < 0) @@ -32,12 +30,8 @@ int ask_password_agent_open(void) { } void ask_password_agent_close(void) { - - if (agent_pid <= 0) - return; - /* Inform agent that we are done */ - sigterm_wait(TAKE_PID(agent_pid)); + pidref_done_sigterm_wait(&agent_pidref); } int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password) { diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index e155970e313..bb83386c5a2 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -59,11 +59,11 @@ #include "openssl-util.h" #include "os-util.h" #include "path-util.h" +#include "pidref.h" #include "proc-cmdline.h" #include "process-util.h" #include "resize-fs.h" #include "runtime-scope.h" -#include "signal-util.h" #include "siphash24.h" #include "stat-util.h" #include "string-util.h" @@ -2237,7 +2237,6 @@ static int is_loop_device(const char *path) { static int run_fsck(int node_fd, const char *fstype) { int r, exit_status; - pid_t pid; assert(node_fd >= 0); assert(fstype); @@ -2252,12 +2251,13 @@ static int run_fsck(int node_fd, const char *fstype) { return 0; } - r = safe_fork_full( + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork_full( "(fsck)", NULL, &node_fd, 1, /* Leave the node fd open */ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF, - &pid); + &pidref); if (r < 0) return log_debug_errno(r, "Failed to fork off fsck: %m"); if (r == 0) { @@ -2268,7 +2268,7 @@ static int run_fsck(int node_fd, const char *fstype) { _exit(FSCK_OPERATIONAL_ERROR); } - exit_status = wait_for_terminate_and_check("fsck", pid, 0); + exit_status = pidref_wait_for_terminate_and_check("fsck", &pidref, 0); if (exit_status < 0) return log_debug_errno(exit_status, "Failed to fork off fsck: %m"); @@ -4170,15 +4170,13 @@ int dissected_image_acquire_metadata( _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL; _cleanup_free_ char *hostname = NULL, *t = NULL; _cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t child = 0; + _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL; sd_id128_t machine_id = SD_ID128_NULL; unsigned n_meta_initialized = 0; int fds[2 * _META_MAX], r, v; int has_init_system = -1; ssize_t n; - BLOCK_SIGNALS(SIGCHLD); - assert(m); r = dlopen_libmount(); @@ -4203,7 +4201,7 @@ int dissected_image_acquire_metadata( goto finish; } - r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &child); + r = pidref_safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &child); if (r < 0) goto finish; if (r == 0) { @@ -4426,11 +4424,12 @@ int dissected_image_acquire_metadata( }} } - r = wait_for_terminate_and_check("(sd-dissect)", child, 0); - child = 0; + r = pidref_wait_for_terminate_and_check("(sd-dissect)", &child, 0); if (r < 0) goto finish; + TAKE_PIDREF(child); + n = read(error_pipe[0], &v, sizeof(v)); if (n < 0) { r = -errno; diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c index 673460efb65..98c3f6748d4 100644 --- a/src/shared/exec-util.c +++ b/src/shared/exec-util.c @@ -17,6 +17,7 @@ #include "hashmap.h" #include "log.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "serialize.h" #include "stat-util.h" @@ -28,6 +29,10 @@ #define EXIT_SKIP_REMAINING 77 +DEFINE_PRIVATE_HASH_OPS_FULL(pidref_hash_ops_free_free, + PidRef, pidref_hash_func, pidref_compare_func, + pidref_free, char*, free); + /* Put this test here for a lack of better place */ assert_cc(EAGAIN == EWOULDBLOCK); @@ -36,25 +41,25 @@ static int do_spawn( char *argv[], int stdout_fd, bool set_systemd_exec_pid, - pid_t *ret_pid) { + PidRef *ret) { int r; assert(path); - assert(ret_pid); + assert(ret); if (null_or_empty_path(path) > 0) { log_debug("%s is masked, skipping.", path); return 0; } - pid_t pid; - r = safe_fork_full( + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork_full( "(exec-inner)", (const int[]) { STDIN_FILENO, stdout_fd < 0 ? STDOUT_FILENO : stdout_fd, STDERR_FILENO }, /* except_fds= */ NULL, /* n_except_fds= */ 0, FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS, - &pid); + &pidref); if (r < 0) return r; if (r == 0) { @@ -78,7 +83,7 @@ static int do_spawn( _exit(EXIT_FAILURE); } - *ret_pid = pid; + *ret = TAKE_PIDREF(pidref); return 1; } @@ -121,7 +126,6 @@ static int do_execute( STRV_FOREACH(path, paths) { _cleanup_free_ char *t = NULL; _cleanup_close_ int fd = -EBADF; - pid_t pid; t = path_join(root, *path); if (!t) @@ -161,19 +165,27 @@ static int do_execute( "permission bits. Proceeding anyway.", t); } - r = do_spawn(t, argv, fd, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID), &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = do_spawn(t, argv, fd, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID), &pidref); if (r <= 0) continue; if (parallel_execution) { - r = hashmap_ensure_put(&pids, &trivial_hash_ops_value_free, PID_TO_PTR(pid), t); + _cleanup_(pidref_freep) PidRef *dup = NULL; + r = pidref_dup(&pidref, &dup); + if (r < 0) + return r; + + r = hashmap_ensure_put(&pids, &pidref_hash_ops_free_free, dup, t); if (r < 0) return log_oom(); - t = NULL; + + TAKE_PTR(dup); + TAKE_PTR(t); } else { bool skip_remaining = false; - r = wait_for_terminate_and_check(t, pid, WAIT_LOG_ABNORMAL); + r = pidref_wait_for_terminate_and_check(t, &pidref, WAIT_LOG_ABNORMAL); if (r < 0) return r; if (r > 0) { @@ -211,14 +223,12 @@ static int do_execute( while (!hashmap_isempty(pids)) { _cleanup_free_ char *t = NULL; - pid_t pid; void *p; t = ASSERT_PTR(hashmap_steal_first_key_and_value(pids, &p)); - pid = PTR_TO_PID(p); - assert(pid > 0); + _cleanup_(pidref_freep) PidRef *pidref = p; - r = wait_for_terminate_and_check(t, pid, WAIT_LOG); + r = pidref_wait_for_terminate_and_check(t, pidref, WAIT_LOG); if (r < 0) return r; if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0) @@ -240,7 +250,6 @@ int execute_strv( ExecDirFlags flags) { _cleanup_close_ int fd = -EBADF; - pid_t executor_pid; int r; assert(name); @@ -266,7 +275,8 @@ int execute_strv( const char *process_name = strjoina("(", name, ")"); - r = safe_fork(process_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pid); + PidRef executor_pidref = PIDREF_NULL; + r = pidref_safe_fork(process_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pidref); if (r < 0) return r; if (r == 0) { @@ -274,7 +284,7 @@ int execute_strv( _exit(r < 0 ? EXIT_FAILURE : r); } - r = wait_for_terminate_and_check(process_name, executor_pid, 0); + r = pidref_wait_for_terminate_and_check(process_name, &executor_pidref, 0); if (r < 0) return r; if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0) @@ -560,19 +570,19 @@ int shall_fork_agent(void) { return true; } -int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, pid_t *ret_pid) { +int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, PidRef *ret) { int r; assert(!strv_isempty(argv)); /* Spawns a temporary TTY agent, making sure it goes away when we go away */ - r = safe_fork_full(name, - NULL, - (int*) except, /* safe_fork_full only changes except if you pass in FORK_PACK_FDS, which we don't */ - n_except, - FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE, - ret_pid); + r = pidref_safe_fork_full( + name, + /* stdio_fds= */ NULL, + (int*) except, n_except, /* safe_fork_full only changes except if you pass in FORK_PACK_FDS, which we don't */ + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE, + ret); if (r < 0) return r; if (r > 0) diff --git a/src/shared/exec-util.h b/src/shared/exec-util.h index bb825e99690..245b7773f4b 100644 --- a/src/shared/exec-util.h +++ b/src/shared/exec-util.h @@ -62,5 +62,5 @@ ExecCommandFlags exec_command_flags_from_string(const char *s); int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]); int shall_fork_agent(void); -int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, pid_t *ret_pid); -#define fork_agent(name, except, n_except, ret_pid, ...) _fork_agent(name, STRV_MAKE(__VA_ARGS__), except, n_except, ret_pid) +int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, PidRef *ret); +#define fork_agent(name, except, n_except, ret, ...) _fork_agent(name, STRV_MAKE(__VA_ARGS__), except, n_except, ret) diff --git a/src/shared/pager.c b/src/shared/pager.c index 2b66dc91d20..203e6503889 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -14,6 +14,7 @@ #include "locale-util.h" #include "log.h" #include "pager.h" +#include "pidref.h" #include "process-util.h" #include "signal-util.h" #include "string-util.h" @@ -288,8 +289,10 @@ void pager_close(void) { stdout_redirected = stderr_redirected = false; (void) kill(pager_pid, SIGCONT); - (void) wait_for_terminate(TAKE_PID(pager_pid), NULL); - pager_pid = 0; + _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); } bool pager_have(void) { @@ -299,7 +302,6 @@ bool pager_have(void) { int show_man_page(const char *desc, bool null_stdio) { const char *args[4] = { "man", NULL, NULL, NULL }; const char *e = NULL; - pid_t pid; size_t k; int r; @@ -319,7 +321,11 @@ int show_man_page(const char *desc, bool null_stdio) { } else args[1] = desc; - r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork( + "(man)", + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, + &pidref); if (r < 0) return r; if (r == 0) { @@ -329,5 +335,5 @@ int show_man_page(const char *desc, bool null_stdio) { _exit(EXIT_FAILURE); } - return wait_for_terminate_and_check(NULL, pid, 0); + return pidref_wait_for_terminate_and_check(NULL, &pidref, 0); } diff --git a/src/shared/polkit-agent.c b/src/shared/polkit-agent.c index 491b494b1e7..5b4e5db819e 100644 --- a/src/shared/polkit-agent.c +++ b/src/shared/polkit-agent.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include -#include #include #include "bus-util.h" @@ -9,19 +8,19 @@ #include "fd-util.h" #include "io-util.h" #include "log.h" +#include "pidref.h" #include "polkit-agent.h" -#include "process-util.h" #include "stdio-util.h" #if ENABLE_POLKIT -static pid_t agent_pid = 0; +static PidRef agent_pidref = PIDREF_NULL; int polkit_agent_open(void) { _cleanup_close_pair_ int pipe_fd[2] = EBADF_PAIR; char notify_fd[DECIMAL_STR_MAX(int) + 1]; int r; - if (agent_pid > 0) + if (pidref_is_set(&agent_pidref)) return 0; /* Clients that run as root don't need to activate/query polkit */ @@ -40,7 +39,7 @@ int polkit_agent_open(void) { r = fork_agent("(polkit-agent)", &pipe_fd[1], 1, - &agent_pid, + &agent_pidref, POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback"); @@ -57,12 +56,8 @@ int polkit_agent_open(void) { } void polkit_agent_close(void) { - - if (agent_pid <= 0) - return; - /* Inform agent that we are done */ - sigterm_wait(TAKE_PID(agent_pid)); + pidref_done_sigterm_wait(&agent_pidref); } #else diff --git a/src/shared/tests.c b/src/shared/tests.c index c851278d068..55464c3553f 100644 --- a/src/shared/tests.c +++ b/src/shared/tests.c @@ -448,7 +448,12 @@ int assert_signal_internal(int *ret_signal) { return ASSERT_SIGNAL_FORK_CHILD; } - r = wait_for_terminate(r, &siginfo); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_set_pid(&pidref, r); + if (r < 0) + return r; + + r = pidref_wait_for_terminate(&pidref, &siginfo); if (r < 0) return r; diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c index 5d691d3d472..7705097c6cf 100644 --- a/src/sulogin-shell/sulogin-shell.c +++ b/src/sulogin-shell/sulogin-shell.c @@ -16,6 +16,7 @@ #include "initrd-util.h" #include "log.h" #include "main-func.h" +#include "pidref.h" #include "proc-cmdline.h" #include "process-util.h" #include "special.h" @@ -66,10 +67,10 @@ static int start_target(sd_bus *bus, const char *target) { } static int fork_wait(const char* const cmdline[]) { - pid_t pid; int r; - r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref); if (r < 0) return r; if (r == 0) { @@ -79,7 +80,7 @@ static int fork_wait(const char* const cmdline[]) { _exit(EXIT_FAILURE); /* Operational error */ } - return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL); + return pidref_wait_for_terminate_and_check(cmdline[0], &pidref, WAIT_LOG_ABNORMAL); } static void print_mode(const char* mode) { diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 7b60dd346b5..33a5ea8bcda 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -48,6 +48,7 @@ #include "parse-argument.h" #include "parse-util.h" #include "path-util.h" +#include "pidref.h" #include "pretty-print.h" #include "process-util.h" #include "rm-rf.h" @@ -2139,14 +2140,15 @@ static int merge(ImageClass image_class, bool no_reload, int noexec, Hashmap *images) { - pid_t pid; + int r; (void) dlopen_cryptsetup(); (void) dlopen_libblkid(); (void) dlopen_libmount(); - r = safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pidref); if (r < 0) return log_error_errno(r, "Failed to fork off child: %m"); if (r == 0) { @@ -2162,7 +2164,7 @@ static int merge(ImageClass image_class, _exit(r > 0 ? EXIT_SUCCESS : 123); /* 123 means: didn't find any extensions */ } - r = wait_for_terminate_and_check("(sd-merge)", pid, WAIT_LOG_ABNORMAL); + r = pidref_wait_for_terminate_and_check("(sd-merge)", &pidref, WAIT_LOG_ABNORMAL); if (r < 0) return r; if (r == 123) /* exit code 123 means: didn't do anything */ diff --git a/src/systemctl/systemctl-sysv-compat.c b/src/systemctl/systemctl-sysv-compat.c index 3905a678b6d..adc73c310ec 100644 --- a/src/systemctl/systemctl-sysv-compat.c +++ b/src/systemctl/systemctl-sysv-compat.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include @@ -9,6 +8,7 @@ #include "log.h" #include "path-lookup.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "string-util.h" #include "strv.h" @@ -56,7 +56,6 @@ int enable_sysv_units(const char *verb, char **args) { bool found_native = false, found_sysv; const char *name; unsigned c = 1; - pid_t pid; int j; name = args[f++]; @@ -122,7 +121,8 @@ int enable_sysv_units(const char *verb, char **args) { if (!arg_quiet) log_info("Executing: %s", l); - j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + j = pidref_safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref); if (j < 0) return j; if (j == 0) { @@ -132,7 +132,7 @@ int enable_sysv_units(const char *verb, char **args) { _exit(EXIT_FAILURE); } - j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL); + j = pidref_wait_for_terminate_and_check("sysv-install", &pidref, WAIT_LOG_ABNORMAL); if (j < 0) return j; if (streq(verb, "is-enabled")) { diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c index 2cbc26ea539..b48be8bab01 100644 --- a/src/sysupdate/sysupdate-resource.c +++ b/src/sysupdate/sysupdate-resource.c @@ -21,6 +21,7 @@ #include "gpt.h" #include "hexdecoct.h" #include "import-util.h" +#include "pidref.h" #include "process-util.h" #include "sort-util.h" #include "stat-util.h" @@ -274,7 +275,6 @@ static int download_manifest( _cleanup_close_pair_ int pfd[2] = EBADF_PAIR; _cleanup_fclose_ FILE *manifest = NULL; size_t size = 0; - pid_t pid; int r; assert(url); @@ -293,11 +293,13 @@ static int download_manifest( log_info("%s Acquiring manifest file %s%s", glyph(GLYPH_DOWNLOAD), suffixed_url, glyph(GLYPH_ELLIPSIS)); - r = safe_fork_full("(sd-pull)", - (int[]) { -EBADF, pfd[1], STDERR_FILENO }, - 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( + "(sd-pull)", + (int[]) { -EBADF, pfd[1], STDERR_FILENO }, + NULL, 0, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG, + &pidref); if (r < 0) return r; if (r == 0) { @@ -337,7 +339,7 @@ static int download_manifest( manifest = safe_fclose(manifest); - r = wait_for_terminate_and_check("(sd-pull)", pid, WAIT_LOG); + r = pidref_wait_for_terminate_and_check("(sd-pull)", &pidref, WAIT_LOG); if (r < 0) return r; if (r != 0) diff --git a/src/test/test-argv-util.c b/src/test/test-argv-util.c index f7a99ff26d9..f449f2aefa2 100644 --- a/src/test/test-argv-util.c +++ b/src/test/test-argv-util.c @@ -59,53 +59,38 @@ static void test_rename_process_now(const char *p, int ret) { } static void test_rename_process_one(const char *p, int ret) { - siginfo_t si; - pid_t pid; + int r; log_info("/* %s(%s) */", __func__, p); - pid = fork(); - assert_se(pid >= 0); + r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL)); - if (pid == 0) { + if (r == 0) { /* child */ test_rename_process_now(p, ret); _exit(EXIT_SUCCESS); } - - assert_se(wait_for_terminate(pid, &si) >= 0); - assert_se(si.si_code == CLD_EXITED); - assert_se(si.si_status == EXIT_SUCCESS); } TEST(rename_process_invalid) { - assert_se(rename_process(NULL) == -EINVAL); - assert_se(rename_process("") == -EINVAL); + ASSERT_ERROR(rename_process(NULL), EINVAL); + ASSERT_ERROR(rename_process(""), EINVAL); } TEST(rename_process_multi) { - pid_t pid; - - pid = fork(); - assert_se(pid >= 0); - - if (pid > 0) { - siginfo_t si; + int r; - assert_se(wait_for_terminate(pid, &si) >= 0); - assert_se(si.si_code == CLD_EXITED); - assert_se(si.si_status == EXIT_SUCCESS); + r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL)); - return; + if (r == 0) { + /* child */ + test_rename_process_now("one", 1); + test_rename_process_now("more", 0); /* longer than "one", hence truncated */ + (void) setresuid(99, 99, 99); /* change uid when running privileged */ + test_rename_process_now("time!", 0); + test_rename_process_now("0", 1); /* shorter than "one", should fit */ + _exit(EXIT_SUCCESS); } - - /* child */ - test_rename_process_now("one", 1); - test_rename_process_now("more", 0); /* longer than "one", hence truncated */ - (void) setresuid(99, 99, 99); /* change uid when running privileged */ - test_rename_process_now("time!", 0); - test_rename_process_now("0", 1); /* shorter than "one", should fit */ - _exit(EXIT_SUCCESS); } TEST(rename_process) { diff --git a/src/test/test-data-fd-util.c b/src/test/test-data-fd-util.c index 97b5cd4a7e5..0a4ce4fdd43 100644 --- a/src/test/test-data-fd-util.c +++ b/src/test/test-data-fd-util.c @@ -7,6 +7,7 @@ #include "data-fd-util.h" #include "fd-util.h" #include "memfd-util.h" +#include "pidref.h" #include "process-util.h" #include "tests.h" @@ -33,7 +34,7 @@ static void assert_equal_fd(int fd1, int fd2) { TEST(copy_data_fd) { _cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF; _cleanup_close_pair_ int sfd[2] = EBADF_PAIR; - _cleanup_(sigkill_waitp) pid_t pid = -1; + _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; int r; fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC); @@ -66,7 +67,7 @@ TEST(copy_data_fd) { assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0); - r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid); + r = pidref_safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref); assert_se(r >= 0); if (r == 0) { diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 973387b3de8..6c05b3e6a7e 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -246,18 +246,17 @@ static bool apparmor_restrict_unprivileged_userns(void) { } static bool have_userns_privileges(void) { - pid_t pid; + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; int r; if (apparmor_restrict_unprivileged_userns()) return false; - r = safe_fork("(sd-test-check-userns)", - FORK_RESET_SIGNALS | - FORK_CLOSE_ALL_FDS | - FORK_DEATHSIG_SIGKILL, - &pid); - ASSERT_OK(r); + r = ASSERT_OK(pidref_safe_fork( + "(sd-test-check-userns)", + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL, + &pidref)); + if (r == 0) { /* Keep CAP_SYS_ADMIN if we have it to ensure we give an * accurate result to the caller. Some kernels have a @@ -282,7 +281,7 @@ static bool have_userns_privileges(void) { * EXIT_SUCCESS => we can use user namespaces * EXIT_FAILURE => we can NOT use user namespaces * 2 => some other error occurred */ - r = wait_for_terminate_and_check("(sd-test-check-userns)", pid, 0); + r = pidref_wait_for_terminate_and_check("(sd-test-check-userns)", &pidref, 0); if (!IN_SET(r, EXIT_SUCCESS, EXIT_FAILURE)) log_debug("Failed to check if user namespaces can be used, assuming not."); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index c5f014c6301..38d92299467 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -12,6 +12,7 @@ #include "memfd-util.h" #include "parse-util.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "random-util.h" #include "rm-rf.h" @@ -492,7 +493,6 @@ TEST(read_full_file_socket) { union sockaddr_union sa; const char *j, *jj; size_t size; - pid_t pid; int r; ASSERT_OK(listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0)); @@ -513,7 +513,8 @@ TEST(read_full_file_socket) { /* Bind the *client* socket to some randomized name, to verify that this works correctly. */ ASSERT_OK(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64())); - ASSERT_OK(r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid)); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = ASSERT_OK(pidref_safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref)); if (r == 0) { union sockaddr_union peer = {}; socklen_t peerlen = sizeof(peer); @@ -540,7 +541,7 @@ TEST(read_full_file_socket) { ASSERT_EQ(size, strlen(TEST_STR)); ASSERT_STREQ(data, TEST_STR); - ASSERT_OK(wait_for_terminate_and_check("(server)", pid, WAIT_LOG)); + ASSERT_OK(pidref_wait_for_terminate_and_check("(server)", &pidref, WAIT_LOG)); #undef TEST_STR } diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 723cc8d0a10..51b7b146fe3 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -12,6 +12,7 @@ #include "fs-util.h" #include "mkdir.h" #include "path-util.h" +#include "pidref.h" #include "process-util.h" #include "random-util.h" #include "rm-rf.h" @@ -743,30 +744,29 @@ TEST(xopenat_lock_full) { _cleanup_(rm_rf_physical_and_freep) char *t = NULL; _cleanup_close_ int tfd = -EBADF, fd = -EBADF; siginfo_t si; + int r; - assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0); + ASSERT_OK((tfd = mkdtemp_open(NULL, 0, &t))); /* Test that we can acquire an exclusive lock on a directory in one process, remove the directory, * and close the file descriptor and still properly create the directory and acquire the lock in * another process. */ - fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX); - assert_se(fd >= 0); - assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0); - assert_se(fd_verify_directory(fd) >= 0); - assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN); + fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX)); + ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0)); + ASSERT_OK(fd_verify_directory(fd)); + ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN); - pid_t pid = fork(); - assert_se(pid >= 0); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = ASSERT_OK(pidref_safe_fork("(lock)", FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref)); - if (pid == 0) { + if (r == 0) { safe_close(fd); - fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX); - assert_se(fd >= 0); - assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0); - assert_se(fd_verify_directory(fd) >= 0); - assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN); + fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX)); + ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0)); + ASSERT_OK(fd_verify_directory(fd)); + ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN); _exit(EXIT_SUCCESS); } @@ -777,16 +777,16 @@ TEST(xopenat_lock_full) { * for a little and assume that's enough time for the child process to get along far enough. It * doesn't matter if it doesn't get far enough, in that case we just won't trigger the fallback logic * in xopenat_lock_full(), but the test will still succeed. */ - assert_se(usleep_safe(20 * USEC_PER_MSEC) >= 0); + ASSERT_OK(usleep_safe(20 * USEC_PER_MSEC)); - assert_se(unlinkat(tfd, "abc", AT_REMOVEDIR) >= 0); + ASSERT_OK(unlinkat(tfd, "abc", AT_REMOVEDIR)); fd = safe_close(fd); - assert_se(wait_for_terminate(pid, &si) >= 0); - assert_se(si.si_code == CLD_EXITED); + ASSERT_OK(pidref_wait_for_terminate(&pidref, &si)); + ASSERT_EQ(si.si_code, CLD_EXITED); - assert_se(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF); - assert_se(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF); + ASSERT_ERROR(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF); + ASSERT_ERROR(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF); } TEST(linkat_replace) { diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index f162075c7c4..1c43c7ab10e 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -94,7 +94,7 @@ TEST(tmpdir) { static void test_shareable_ns(unsigned long nsflag) { _cleanup_close_pair_ int s[2] = EBADF_PAIR; bool permission_denied = false; - pid_t pid1, pid2, pid3; + _cleanup_(pidref_done) PidRef pidref1 = PIDREF_NULL, pidref2 = PIDREF_NULL, pidref3 = PIDREF_NULL; int r, n = 0; siginfo_t si; @@ -105,51 +105,48 @@ static void test_shareable_ns(unsigned long nsflag) { ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s)); - pid1 = fork(); - ASSERT_OK_ERRNO(pid1); + r = ASSERT_OK(pidref_safe_fork("(share-ns-1)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref1)); - if (pid1 == 0) { + if (r == 0) { r = setup_shareable_ns(s, nsflag); if (!ERRNO_IS_PRIVILEGE(r)) ASSERT_OK(r); _exit(r >= 0 ? r : EX_NOPERM); } - pid2 = fork(); - ASSERT_OK_ERRNO(pid2); + r = ASSERT_OK(pidref_safe_fork("(share-ns-2)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref2)); - if (pid2 == 0) { + if (r == 0) { r = setup_shareable_ns(s, nsflag); if (!ERRNO_IS_PRIVILEGE(r)) ASSERT_OK(r); _exit(r >= 0 ? r : EX_NOPERM); } - pid3 = fork(); - ASSERT_OK_ERRNO(pid3); + r = ASSERT_OK(pidref_safe_fork("(share-ns-3)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref3)); - if (pid3 == 0) { + if (r == 0) { r = setup_shareable_ns(s, nsflag); if (!ERRNO_IS_PRIVILEGE(r)) ASSERT_OK(r); _exit(r >= 0 ? r : EX_NOPERM); } - ASSERT_OK(wait_for_terminate(pid1, &si)); + ASSERT_OK(pidref_wait_for_terminate(&pidref1, &si)); ASSERT_EQ(si.si_code, CLD_EXITED); if (si.si_status == EX_NOPERM) permission_denied = true; else n += si.si_status; - ASSERT_OK(wait_for_terminate(pid2, &si)); + ASSERT_OK(pidref_wait_for_terminate(&pidref2, &si)); ASSERT_EQ(si.si_code, CLD_EXITED); if (si.si_status == EX_NOPERM) permission_denied = true; else n += si.si_status; - ASSERT_OK(wait_for_terminate(pid3, &si)); + ASSERT_OK(pidref_wait_for_terminate(&pidref3, &si)); ASSERT_EQ(si.si_code, CLD_EXITED); if (si.si_status == EX_NOPERM) permission_denied = true; @@ -203,7 +200,6 @@ TEST(protect_kernel_logs) { .protect_kernel_logs = true, .root_directory_fd = -EBADF, }; - pid_t pid; int r; if (geteuid() > 0) { @@ -224,10 +220,9 @@ TEST(protect_kernel_logs) { } ASSERT_OK(r); - pid = fork(); - ASSERT_OK_ERRNO(pid); + r = ASSERT_OK(safe_fork("(protect)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL)); - if (pid == 0) { + if (r == 0) { _cleanup_close_ int fd = -EBADF; ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC)); @@ -239,8 +234,6 @@ TEST(protect_kernel_logs) { _exit(EXIT_SUCCESS); } - - ASSERT_OK_EQ(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG), EXIT_SUCCESS); } TEST(idmapping_supported) { diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index e1a43b8b644..3df3e747ffa 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -464,7 +464,6 @@ TEST(find_executable) { static void test_find_executable_exec_one(const char *path) { _cleanup_free_ char *t = NULL; _cleanup_close_ int fd = -EBADF; - pid_t pid; int r; r = find_executable_full(path, NULL, NULL, false, &t, &fd); @@ -476,15 +475,13 @@ static void test_find_executable_exec_one(const char *path) { if (path_is_absolute(path)) ASSERT_STREQ(t, path); - pid = fork(); - assert_se(pid >= 0); - if (pid == 0) { + r = ASSERT_OK(safe_fork("(find-exec)", FORK_LOG|FORK_DEATHSIG_SIGKILL|FORK_WAIT, /* ret_pid= */ NULL)); + + if (r == 0) { r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL)); log_error_errno(r, "[f]execve: %m"); _exit(EXIT_FAILURE); } - - assert_se(wait_for_terminate_and_check(t, pid, WAIT_LOG) == 0); } TEST(find_executable_exec) { diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index b7978453344..d4f39bf3ee9 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -263,7 +263,6 @@ TEST(pid_get_cmdline_harder) { _cleanup_close_ int fd = -EBADF; _cleanup_free_ char *line = NULL; _cleanup_strv_free_ char **args = NULL; - pid_t pid; int r; if (geteuid() != 0) { @@ -286,297 +285,286 @@ TEST(pid_get_cmdline_harder) { } #endif - pid = fork(); - if (pid > 0) { - siginfo_t si; - - (void) wait_for_terminate(pid, &si); - - ASSERT_EQ(si.si_code, CLD_EXITED); - ASSERT_OK_ZERO(si.si_status); - - return; - } - - ASSERT_OK_ZERO(pid); - - r = detach_mount_namespace(); - if (r < 0) { - log_warning_errno(r, "detach mount namespace failed: %m"); - if (!ERRNO_IS_PRIVILEGE(r)) - ASSERT_OK(r); - return; - } + r = ASSERT_OK(safe_fork("(cmdline)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL)); + if (r == 0) { + r = detach_mount_namespace(); + if (r < 0) { + log_warning_errno(r, "detach mount namespace failed: %m"); + if (!ERRNO_IS_PRIVILEGE(r)) + ASSERT_OK(r); + return; + } - fd = mkostemp(path, O_CLOEXEC); - ASSERT_OK_ERRNO(fd); + fd = mkostemp(path, O_CLOEXEC); + ASSERT_OK_ERRNO(fd); - /* Note that we don't unmount the following bind-mount at the end of the test because the kernel - * will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */ - if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) { - /* This happens under selinux… Abort the test in this case. */ - log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m"); - ASSERT_TRUE(IN_SET(errno, EPERM, EACCES)); - return; - } + /* Note that we don't unmount the following bind-mount at the end of the test because the kernel + * will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */ + if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) { + /* This happens under selinux… Abort the test in this case. */ + log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m"); + ASSERT_TRUE(IN_SET(errno, EPERM, EACCES)); + return; + } - /* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read - * the cmdline. */ - if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0) - log_warning("Testing without RLIMIT_STACK=infinity"); + /* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read + * the cmdline. */ + if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0) + log_warning("Testing without RLIMIT_STACK=infinity"); - ASSERT_OK_ERRNO(unlink(path)); + ASSERT_OK_ERRNO(unlink(path)); - ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa")); + ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa")); - ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT); + ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "[testa]"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "[testa]"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */ - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */ + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, ""); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, ""); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "…"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "…"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[…"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[…"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[t…"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[t…"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[te…"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[te…"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[tes…"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[tes…"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[test…"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[test…"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[testa]"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[testa]"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "[testa]"); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "[testa]"); + line = mfree(line); - ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); - ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]"))); - args = strv_free(args); + ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); + ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]"))); + args = strv_free(args); /* Test with multiple arguments that don't require quoting */ - ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8); - - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - ASSERT_STREQ(line, "foo bar"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); - ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar"))); - args = strv_free(args); - - ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar quux"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar quux"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "f…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "fo…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo …"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo b…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo ba…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar …"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar q…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar qu…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar quux"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar quux"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar quux"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "foo bar quux"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); - ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux"))); - args = strv_free(args); - - ASSERT_OK_ERRNO(ftruncate(fd, 0)); - ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc")); - - ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT); - - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "[aaaa bbbb cccc]"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "[aaaa bbb…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "[aaaa bbbb…"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line)); - log_debug("'%s'", line); - ASSERT_STREQ(line, "[aaaa bbbb …"); - line = mfree(line); - - ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); - ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]"))); - args = strv_free(args); - - /* Test with multiple arguments that do require quoting */ + ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8); + + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + ASSERT_STREQ(line, "foo bar"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); + ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar"))); + args = strv_free(args); + + ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar quux"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar quux"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "f…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "fo…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo …"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo b…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo ba…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar …"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar q…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar qu…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar quux"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar quux"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar quux"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "foo bar quux"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); + ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux"))); + args = strv_free(args); + + ASSERT_OK_ERRNO(ftruncate(fd, 0)); + ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc")); + + ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT); + + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "[aaaa bbbb cccc]"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "[aaaa bbb…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "[aaaa bbbb…"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line)); + log_debug("'%s'", line); + ASSERT_STREQ(line, "[aaaa bbbb …"); + line = mfree(line); + + ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args)); + ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]"))); + args = strv_free(args); + + /* Test with multiple arguments that do require quoting */ #define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0" #define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\"" #define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'" #define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``") - ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET)); - ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1)); - ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1))); + ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET)); + ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1)); + ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1))); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line)); - log_debug("got: ==%s==", line); - log_debug("exp: ==%s==", EXPECT1); - ASSERT_STREQ(line, EXPECT1); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line)); + log_debug("got: ==%s==", line); + log_debug("exp: ==%s==", EXPECT1); + ASSERT_STREQ(line, EXPECT1); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line)); - log_debug("got: ==%s==", line); - log_debug("exp: ==%s==", EXPECT1p); - ASSERT_STREQ(line, EXPECT1p); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line)); + log_debug("got: ==%s==", line); + log_debug("exp: ==%s==", EXPECT1p); + ASSERT_STREQ(line, EXPECT1p); + line = mfree(line); - ASSERT_OK(pid_get_cmdline_strv(0, 0, &args)); - ASSERT_TRUE(strv_equal(args, EXPECT1v)); - args = strv_free(args); + ASSERT_OK(pid_get_cmdline_strv(0, 0, &args)); + ASSERT_TRUE(strv_equal(args, EXPECT1v)); + args = strv_free(args); #define CMDLINE2 "foo\0\1\2\3\0\0" #define EXPECT2 "foo \"\\001\\002\\003\"" #define EXPECT2p "foo $'\\001\\002\\003'" #define EXPECT2v STRV_MAKE("foo", "\1\2\3") - ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET)); - ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2)); - ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2)); + ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET)); + ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2)); + ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2)); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line)); - log_debug("got: ==%s==", line); - log_debug("exp: ==%s==", EXPECT2); - ASSERT_STREQ(line, EXPECT2); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line)); + log_debug("got: ==%s==", line); + log_debug("exp: ==%s==", EXPECT2); + ASSERT_STREQ(line, EXPECT2); + line = mfree(line); - ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line)); - log_debug("got: ==%s==", line); - log_debug("exp: ==%s==", EXPECT2p); - ASSERT_STREQ(line, EXPECT2p); - line = mfree(line); + ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line)); + log_debug("got: ==%s==", line); + log_debug("exp: ==%s==", EXPECT2p); + ASSERT_STREQ(line, EXPECT2p); + line = mfree(line); - ASSERT_OK(pid_get_cmdline_strv(0, 0, &args)); - ASSERT_TRUE(strv_equal(args, EXPECT2v)); - args = strv_free(args); + ASSERT_OK(pid_get_cmdline_strv(0, 0, &args)); + ASSERT_TRUE(strv_equal(args, EXPECT2v)); + args = strv_free(args); - safe_close(fd); - _exit(EXIT_SUCCESS); + safe_close(fd); + _exit(EXIT_SUCCESS); + } } TEST(getpid_cached) { - siginfo_t si; - pid_t a, b, c, d, e, f, child; + pid_t a, b, c, d, e, f; + int r; a = getpid(); b = getpid_cached(); @@ -585,10 +573,9 @@ TEST(getpid_cached) { ASSERT_EQ(a, b); ASSERT_EQ(a, c); - child = fork(); - ASSERT_OK_ERRNO(child); + r = ASSERT_OK(safe_fork("(getpid)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL)); - if (child == 0) { + if (r == 0) { /* In child */ a = getpid(); b = getpid_cached(); @@ -606,10 +593,6 @@ TEST(getpid_cached) { ASSERT_EQ(a, d); ASSERT_EQ(a, e); ASSERT_EQ(a, f); - - ASSERT_OK(wait_for_terminate(child, &si)); - ASSERT_EQ(si.si_status, 0); - ASSERT_EQ(si.si_code, CLD_EXITED); } TEST(getpid_measure) { @@ -641,8 +624,6 @@ TEST(safe_fork) { pid_t pid; int r; - BLOCK_SIGNALS(SIGCHLD); - r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid); ASSERT_OK(r); @@ -653,11 +634,14 @@ TEST(safe_fork) { _exit(88); } - ASSERT_OK(wait_for_terminate(pid, &status)); + _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); - _cleanup_(pidref_done) PidRef child = PIDREF_NULL; + pidref_done(&child); r = pidref_safe_fork("(test-child)", FORK_DETACH, &child); if (r == 0) { /* Don't freeze so this doesn't linger around forever in case something goes wrong. */ diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 024a0fd3a21..f1039319fd8 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -23,6 +23,7 @@ #include "locale-util.h" #include "log.h" #include "main-func.h" +#include "pidref.h" #include "proc-cmdline.h" #include "process-util.h" #include "stdio-util.h" @@ -255,7 +256,6 @@ assert_cc(STRLEN(SYSTEMD_DEFAULT_KEYMAP) > 0); static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) { const char* args[8]; unsigned i = 0; - pid_t pid; int r; assert(vc); @@ -286,7 +286,8 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) { log_debug("Executing \"%s\"...", strnull(cmd)); } - r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref); if (r < 0) return r; if (r == 0) { @@ -294,13 +295,12 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) { _exit(EXIT_FAILURE); } - return wait_for_terminate_and_check(KBD_LOADKEYS, pid, WAIT_LOG); + return pidref_wait_for_terminate_and_check(KBD_LOADKEYS, &pidref, WAIT_LOG); } static int font_load_and_wait(const char *vc, Context *c) { const char* args[9]; unsigned i = 0; - pid_t pid; int r; assert(vc); @@ -337,7 +337,8 @@ static int font_load_and_wait(const char *vc, Context *c) { log_debug("Executing \"%s\"...", strnull(cmd)); } - r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref); if (r < 0) return r; if (r == 0) { @@ -348,7 +349,7 @@ static int font_load_and_wait(const char *vc, Context *c) { /* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. This might mean various * things, but in particular lack of a graphical console. Let's be generous and not treat this as an * error. */ - r = wait_for_terminate_and_check(KBD_SETFONT, pid, WAIT_LOG_ABNORMAL); + r = pidref_wait_for_terminate_and_check(KBD_SETFONT, &pidref, WAIT_LOG_ABNORMAL); if (r == EX_OSERR) log_notice(KBD_SETFONT " failed with a \"system error\" (EX_OSERR), ignoring."); else if (r >= 0 && r != EXIT_SUCCESS)