111 lines
4.5 KiB
Diff
111 lines
4.5 KiB
Diff
From bfde9421af1458e18999d787b1ab46a6a33e8bb6 Mon Sep 17 00:00:00 2001
|
|
From: Martin Wilck <mwilck@suse.com>
|
|
Date: Wed, 6 Nov 2019 12:24:41 +0100
|
|
Subject: [PATCH 0573/1760] udevd: wait for workers to finish when exiting
|
|
|
|
On some systems with lots of devices, device probing for certain drivers can
|
|
take a very long time. If systemd-udevd detects a timeout and kills the worker
|
|
running modprobe using SIGKILL, some devices will not be probed, or end up in
|
|
unusable state. The --event-timeout option can be used to modify the maximum
|
|
time spent in an uevent handler. But if systemd-udevd exits, it uses a
|
|
different timeout, hard-coded to 30s, and exits when this timeout expires,
|
|
causing all workers to be KILLed by systemd afterwards. In practice, this may
|
|
lead to workers being killed after significantly less time than specified with
|
|
the event-timeout. This is particularly significant during initrd processing:
|
|
systemd-udevd will be stopped by systemd when initrd-switch-root.target is
|
|
about to be isolated, which usually happens quickly after finding and mounting
|
|
the root FS.
|
|
|
|
If systemd-udevd is started by PID 1 (i.e. basically always), systemd will
|
|
kill both udevd and the workers after expiry of TimeoutStopSec. This is
|
|
actually better than the built-in udevd timeout, because it's more transparent
|
|
and configurable for users. This way users can avoid the mentioned boot problem
|
|
by simply increasing StopTimeoutSec= in systemd-udevd.service.
|
|
|
|
If udevd is not started by systemd (standalone), this is still an
|
|
improvement. udevd will kill hanging workers when the event timeout is
|
|
reached, which is configurable via the udev.event_timeout= kernel
|
|
command line parameter. Before this patch, udevd would simply exit with
|
|
workers still running, which would then become zombie processes.
|
|
|
|
With the timeout removed, the sd_event_now() assertion in manager_exit() can be
|
|
dropped.
|
|
|
|
NOTE: This patch is modified to fit current code. The first part (some NEWS) has
|
|
been removed, and this modification will not affect functionality.
|
|
|
|
https://github.com/systemd/systemd/pull/13961/commits/bfde9421af1458e18999d787b1ab46a6a33e8bb6
|
|
Reference: https://github.com/systemd/systemd/commit/bfde9421af1458e18999d787b1ab46a6a33e8bb6
|
|
Conflict: NA
|
|
---
|
|
NEWS | 13 +++++++++++++
|
|
src/udev/udevd.c | 21 ---------------------
|
|
2 files changed, 13 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/NEWS b/NEWS
|
|
index de4f93a..aabafb9 100644
|
|
--- a/NEWS
|
|
+++ b/NEWS
|
|
@@ -1,5 +1,18 @@
|
|
systemd System and Service Manager
|
|
|
|
+CHANGES WITH 244(We backported this to V243):
|
|
+
|
|
+ * systemd-udevd: removed the 30s timeout for killing stale workers on
|
|
+ exit. systemd-udevd now waits for workers to finish. The hard-coded
|
|
+ exit timeout of 30s was too short for some large installations, where
|
|
+ driver initialization could be prematurely interrupted during initrd
|
|
+ processing if the root file system had been mounted and init was
|
|
+ preparing to switch root. If udevd is run without systemd and workers
|
|
+ are hanging while udevd receives an exit signal, udevd will now exit
|
|
+ when udev.event_timeout is reached for the last hanging worker. With
|
|
+ systemd, the exit timeout can additionally be configured using
|
|
+ TimeoutStopSec= in systemd-udevd.service.
|
|
+
|
|
CHANGES WITH 243:
|
|
|
|
* This release enables unprivileged programs (i.e. requiring neither
|
|
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
|
|
index cb51230..0a2c8a2 100644
|
|
--- a/src/udev/udevd.c
|
|
+++ b/src/udev/udevd.c
|
|
@@ -777,21 +777,7 @@ set_delaying_seqnum:
|
|
return true;
|
|
}
|
|
|
|
-static int on_exit_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
|
|
- Manager *manager = userdata;
|
|
-
|
|
- assert(manager);
|
|
-
|
|
- log_error("Giving up waiting for workers to finish.");
|
|
- sd_event_exit(manager->event, -ETIMEDOUT);
|
|
-
|
|
- return 1;
|
|
-}
|
|
-
|
|
static void manager_exit(Manager *manager) {
|
|
- uint64_t usec;
|
|
- int r;
|
|
-
|
|
assert(manager);
|
|
|
|
manager->exit = true;
|
|
@@ -811,13 +797,6 @@ static void manager_exit(Manager *manager) {
|
|
/* discard queued events and kill workers */
|
|
event_queue_cleanup(manager, EVENT_QUEUED);
|
|
manager_kill_workers(manager);
|
|
-
|
|
- assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0);
|
|
-
|
|
- r = sd_event_add_time(manager->event, NULL, CLOCK_MONOTONIC,
|
|
- usec + 30 * USEC_PER_SEC, USEC_PER_SEC, on_exit_timeout, manager);
|
|
- if (r < 0)
|
|
- return;
|
|
}
|
|
|
|
/* reload requested, HUP signal received, rules changed, builtin changed */
|
|
--
|
|
2.19.1
|
|
|