#include "device-private.h"
#include "device-util.h"
+#include "event-util.h"
#include "fd-util.h"
#include "path-util.h"
#include "process-util.h"
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;
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;
}
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;
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 */
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);
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");
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);
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,