udev: wait for an extra time before the manager kills workers

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 <sushmita.bhattacharya@oracle.com>
This commit is contained in:
Yu Watanabe 2024-01-03 04:23:22 +09:00
parent 11706971e8
commit b16c6076cb
2 changed files with 33 additions and 1 deletions

View file

@ -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

View file

@ -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);
}