Merge pull request #30532 from yuwata/udev-extend-timeout-kill-worker
udev: extend timeout to prevent kill worker
This commit is contained in:
+27
-1
@@ -332,6 +332,28 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use
|
||||
return 1;
|
||||
}
|
||||
|
||||
static usec_t extra_timeout_usec(void) {
|
||||
static usec_t saved = 10 * USEC_PER_SEC;
|
||||
static bool parsed = false;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
if (parsed)
|
||||
return saved;
|
||||
|
||||
parsed = true;
|
||||
|
||||
e = getenv("SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC");
|
||||
if (!e)
|
||||
return saved;
|
||||
|
||||
r = parse_sec(e, &saved);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse $SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC=%s, ignoring: %m", e);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static void worker_attach_event(Worker *worker, Event *event) {
|
||||
Manager *manager = ASSERT_PTR(ASSERT_PTR(worker)->manager);
|
||||
sd_event *e = ASSERT_PTR(manager->event);
|
||||
@@ -349,8 +371,12 @@ static void worker_attach_event(Worker *worker, Event *event) {
|
||||
udev_warn_timeout(manager->timeout_usec), USEC_PER_SEC,
|
||||
on_event_timeout_warning, event);
|
||||
|
||||
/* Manager.timeout_usec is also used as the timeout for running programs specified in
|
||||
* IMPORT{program}=, PROGRAM=, or RUN=. Here, let's add an extra time before the manager
|
||||
* kills a worker, to make it possible that the worker detects timed out of spawned programs,
|
||||
* kills them, and finalizes the event. */
|
||||
(void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
|
||||
manager->timeout_usec, USEC_PER_SEC,
|
||||
usec_add(manager->timeout_usec, extra_timeout_usec()), USEC_PER_SEC,
|
||||
on_event_timeout, event);
|
||||
}
|
||||
|
||||
|
||||
+33
-24
@@ -23,6 +23,7 @@ typedef struct Spawn {
|
||||
usec_t timeout_usec;
|
||||
int timeout_signal;
|
||||
usec_t event_birth_usec;
|
||||
usec_t cmd_birth_usec;
|
||||
bool accept_failure;
|
||||
int fd_stdout;
|
||||
int fd_stderr;
|
||||
@@ -163,31 +164,20 @@ static int spawn_wait(Spawn *spawn) {
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(spawn->device, r, "Failed to allocate sd-event object: %m");
|
||||
|
||||
if (spawn->timeout_usec > 0) {
|
||||
usec_t usec, age_usec;
|
||||
|
||||
usec = now(CLOCK_MONOTONIC);
|
||||
age_usec = usec - spawn->event_birth_usec;
|
||||
if (age_usec < spawn->timeout_usec) {
|
||||
if (spawn->timeout_warn_usec > 0 &&
|
||||
spawn->timeout_warn_usec < spawn->timeout_usec &&
|
||||
spawn->timeout_warn_usec > age_usec) {
|
||||
spawn->timeout_warn_usec -= age_usec;
|
||||
|
||||
r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
|
||||
usec + spawn->timeout_warn_usec, USEC_PER_SEC,
|
||||
on_spawn_timeout_warning, spawn);
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(spawn->device, r, "Failed to create timeout warning event source: %m");
|
||||
}
|
||||
|
||||
spawn->timeout_usec -= age_usec;
|
||||
|
||||
if (spawn->timeout_usec != USEC_INFINITY) {
|
||||
if (spawn->timeout_warn_usec < spawn->timeout_usec) {
|
||||
r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
|
||||
usec + spawn->timeout_usec, USEC_PER_SEC, on_spawn_timeout, spawn);
|
||||
usec_add(spawn->cmd_birth_usec, spawn->timeout_warn_usec), USEC_PER_SEC,
|
||||
on_spawn_timeout_warning, spawn);
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(spawn->device, r, "Failed to create timeout event source: %m");
|
||||
return log_device_debug_errno(spawn->device, r, "Failed to create timeout warning event source: %m");
|
||||
}
|
||||
|
||||
r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
|
||||
usec_add(spawn->cmd_birth_usec, spawn->timeout_usec), USEC_PER_SEC,
|
||||
on_spawn_timeout, spawn);
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(spawn->device, r, "Failed to create timeout event source: %m");
|
||||
}
|
||||
|
||||
if (spawn->fd_stdout >= 0) {
|
||||
@@ -240,6 +230,13 @@ int udev_event_spawn(
|
||||
|
||||
int timeout_signal = event->worker ? event->worker->timeout_signal : SIGKILL;
|
||||
usec_t timeout_usec = event->worker ? event->worker->timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
|
||||
usec_t now_usec = now(CLOCK_MONOTONIC);
|
||||
usec_t age_usec = usec_sub_unsigned(now_usec, event->birth_usec);
|
||||
usec_t cmd_timeout_usec = usec_sub_unsigned(timeout_usec, age_usec);
|
||||
if (cmd_timeout_usec <= 0)
|
||||
return log_device_warning_errno(event->dev, SYNTHETIC_ERRNO(ETIME),
|
||||
"The event already takes longer (%s) than the timeout (%s), skipping execution of '%s'.",
|
||||
FORMAT_TIMESPAN(age_usec, 1), FORMAT_TIMESPAN(timeout_usec, 1), cmd);
|
||||
|
||||
/* pipes from child to parent */
|
||||
if (result || log_get_max_level() >= LOG_INFO)
|
||||
@@ -300,10 +297,11 @@ int udev_event_spawn(
|
||||
.cmd = cmd,
|
||||
.pid = pid,
|
||||
.accept_failure = accept_failure,
|
||||
.timeout_warn_usec = udev_warn_timeout(timeout_usec),
|
||||
.timeout_usec = timeout_usec,
|
||||
.timeout_warn_usec = udev_warn_timeout(cmd_timeout_usec),
|
||||
.timeout_usec = cmd_timeout_usec,
|
||||
.timeout_signal = timeout_signal,
|
||||
.event_birth_usec = event->birth_usec,
|
||||
.cmd_birth_usec = now_usec,
|
||||
.fd_stdout = outpipe[READ_END],
|
||||
.fd_stderr = errpipe[READ_END],
|
||||
.result = result,
|
||||
@@ -340,6 +338,17 @@ void udev_event_execute_run(UdevEvent *event) {
|
||||
log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
|
||||
} else {
|
||||
if (event->worker && event->worker->exec_delay_usec > 0) {
|
||||
usec_t timeout_usec = event->worker ? event->worker->timeout_usec : DEFAULT_WORKER_TIMEOUT_USEC;
|
||||
usec_t now_usec = now(CLOCK_MONOTONIC);
|
||||
usec_t age_usec = usec_sub_unsigned(now_usec, event->birth_usec);
|
||||
|
||||
if (event->worker->exec_delay_usec >= usec_sub_unsigned(timeout_usec, age_usec)) {
|
||||
log_device_warning(event->dev,
|
||||
"Cannot delaying execution of \"%s\" for %s, skipping.",
|
||||
command, FORMAT_TIMESPAN(event->worker->exec_delay_usec, USEC_PER_SEC));
|
||||
continue;
|
||||
}
|
||||
|
||||
log_device_debug(event->dev, "Delaying execution of \"%s\" for %s.",
|
||||
command, FORMAT_TIMESPAN(event->worker->exec_delay_usec, USEC_PER_SEC));
|
||||
(void) usleep_safe(event->worker->exec_delay_usec);
|
||||
|
||||
Reference in New Issue
Block a user