From cdd2dd2d58f34d32ee3957aa05860a513909d400 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 1 Apr 2025 15:54:24 +0900 Subject: [PATCH] udev-spawn: manage spawned processes by PidRef --- src/udev/udev-spawn.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/udev/udev-spawn.c b/src/udev/udev-spawn.c index 22cb0089a44..9a0e242a81b 100644 --- a/src/udev/udev-spawn.c +++ b/src/udev/udev-spawn.c @@ -4,6 +4,7 @@ #include "device-private.h" #include "device-util.h" +#include "event-util.h" #include "fd-util.h" #include "path-util.h" #include "process-util.h" @@ -19,7 +20,7 @@ typedef struct Spawn { sd_device *device; const char *cmd; - pid_t pid; + PidRef pidref; usec_t timeout_warn_usec; usec_t timeout_usec; int timeout_signal; @@ -108,10 +109,10 @@ static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) { DEVICE_TRACE_POINT(spawn_timeout, spawn->device, spawn->cmd); log_device_error(spawn->device, "Spawned process '%s' ["PID_FMT"] timed out after %s, killing.", - spawn->cmd, spawn->pid, + spawn->cmd, spawn->pidref.pid, FORMAT_TIMESPAN(spawn->timeout_usec, USEC_PER_SEC)); - kill_and_sigcont(spawn->pid, spawn->timeout_signal); + pidref_kill_and_sigcont(&spawn->pidref, spawn->timeout_signal); return 1; } @@ -119,7 +120,7 @@ static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *use Spawn *spawn = ASSERT_PTR(userdata); log_device_warning(spawn->device, "Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete.", - spawn->cmd, spawn->pid, + spawn->cmd, spawn->pidref.pid, FORMAT_TIMESPAN(spawn->timeout_warn_usec, USEC_PER_SEC)); return 1; @@ -199,7 +200,7 @@ static int spawn_wait(Spawn *spawn) { return log_device_debug_errno(spawn->device, r, "Failed to enable stderr event source: %m"); } - r = sd_event_add_child(e, &sigchld_source, spawn->pid, WEXITED, on_spawn_sigchld, spawn); + r = event_add_child_pidref(e, &sigchld_source, &spawn->pidref, WEXITED, on_spawn_sigchld, spawn); if (r < 0) return log_device_debug_errno(spawn->device, r, "Failed to create sigchild event source: %m"); /* SIGCHLD should be processed after IO is complete */ @@ -218,11 +219,6 @@ int udev_event_spawn( size_t result_size, bool *ret_truncated) { - _cleanup_close_pair_ int outpipe[2] = EBADF_PAIR, errpipe[2] = EBADF_PAIR; - _cleanup_strv_free_ char **argv = NULL; - char **envp = NULL; - Spawn spawn; - pid_t pid; int r; assert(event); @@ -251,16 +247,19 @@ int udev_event_spawn( FORMAT_TIMESPAN(age_usec, 1), FORMAT_TIMESPAN(timeout_usec, 1), cmd); /* pipes from child to parent */ + _cleanup_close_pair_ int outpipe[2] = EBADF_PAIR; if (result || log_get_max_level() >= LOG_INFO) if (pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) != 0) return log_device_error_errno(event->dev, errno, "Failed to create pipe for command '%s': %m", cmd); + _cleanup_close_pair_ int errpipe[2] = EBADF_PAIR; if (log_get_max_level() >= LOG_INFO) if (pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) != 0) return log_device_error_errno(event->dev, errno, "Failed to create pipe for command '%s': %m", cmd); + _cleanup_strv_free_ char **argv = NULL; r = strv_split_full(&argv, cmd, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE); if (r < 0) return log_device_error_errno(event->dev, r, "Failed to split command: %m"); @@ -280,17 +279,20 @@ int udev_event_spawn( free_and_replace(argv[0], program); } + char **envp; r = device_get_properties_strv(event->dev, &envp); if (r < 0) return log_device_error_errno(event->dev, r, "Failed to get device properties"); log_device_debug(event->dev, "Starting '%s'", cmd); - r = safe_fork_full("(spawn)", - (int[]) { -EBADF, outpipe[WRITE_END], errpipe[WRITE_END] }, - 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( + "(spawn)", + (int[]) { -EBADF, outpipe[WRITE_END], errpipe[WRITE_END] }, + 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) return log_device_error_errno(event->dev, r, "Failed to fork() to execute command '%s': %m", cmd); @@ -304,10 +306,10 @@ int udev_event_spawn( outpipe[WRITE_END] = safe_close(outpipe[WRITE_END]); errpipe[WRITE_END] = safe_close(errpipe[WRITE_END]); - spawn = (Spawn) { + Spawn spawn = { .device = event->dev, .cmd = cmd, - .pid = pid, + .pidref = pidref, /* Do not take ownership */ .accept_failure = accept_failure, .timeout_warn_usec = udev_warn_timeout(cmd_timeout_usec), .timeout_usec = cmd_timeout_usec, -- 2.47.3