]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: wait for an extra time before the manager kills workers
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Jan 2024 19:23:22 +0000 (04:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Jan 2024 19:23:22 +0000 (04:23 +0900)
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>
docs/ENVIRONMENT.md
src/udev/udev-manager.c

index 819d5367738bf974fe7d9aa944536bfdeebf5b44..b9a96be82c770be4d378c6dc11e582e74280c788 100644 (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
index 1cf215ed46cb6e2782b3cc93566208451cb5c748..5bf00bb26255abb1e53c89d12b719d9335453bc8 100644 (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);
 }