Skip to content

Commit

Permalink
udev: wait for an extra time before the manager kills workers
Browse files Browse the repository at this point in the history
Otherwise, udev workers cannot detect slow programs invoked by
IMPORT{program}=, PROGRAM=, or RUN=, and whole worker process may be
killed.

Fixes #30436.

Co-authored-by: sushmbha <[email protected]>
  • Loading branch information
yuwata and sushmbha committed Jan 2, 2024
1 parent 1170697 commit b16c607
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs/ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ All tools:
devices sysfs path are actually backed by sysfs. Relaxing this verification
is useful for testing purposes.

* `$SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC=` — Specifies an extra timespan that the
udev manager process waits for a worker process kills slow programs specified
by IMPORT{program}=, PROGRAM=, or RUN=, and finalizes the processing event.
If the worker process cannot finalize the event within the specified timespan,
the worker process is killed by the manager process. Defaults to 10 seconds.

`udevadm` and `systemd-hwdb`:

* `SYSTEMD_HWDB_UPDATE_BYPASS=` — If set to "1", execution of hwdb updates is skipped
Expand Down
28 changes: 27 additions & 1 deletion src/udev/udev-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down

0 comments on commit b16c607

Please sign in to comment.