diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-01-02 20:23:22 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-01-02 20:23:22 +0100 |
commit | b16c6076cb334c9da9602d4bafbf60381d6d630e (patch) | |
tree | 0aee1de1ed2feb832b7e1d9e6534b1fbf1d6ba54 | |
parent | udev-spawn: skip executing RUN= if exec_delay= is too long (diff) | |
download | systemd-b16c6076cb334c9da9602d4bafbf60381d6d630e.tar.xz systemd-b16c6076cb334c9da9602d4bafbf60381d6d630e.zip |
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>
-rw-r--r-- | docs/ENVIRONMENT.md | 6 | ||||
-rw-r--r-- | src/udev/udev-manager.c | 28 |
2 files changed, 33 insertions, 1 deletions
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 819d536773..b9a96be82c 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -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 diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index 1cf215ed46..5bf00bb262 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -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); } |