summaryrefslogtreecommitdiff
path: root/src/udev/udevd.c
diff options
context:
space:
mode:
authorMartin Wilck <mwilck@suse.com>2019-11-06 12:24:41 +0100
committerMartin Wilck <mwilck@suse.com>2019-11-12 12:20:20 +0100
commitbfde9421af1458e18999d787b1ab46a6a33e8bb6 (patch)
treed2101b938dd0a552c1d52a437e80b17d1b04d629 /src/udev/udevd.c
parentc631c3d6a340c13adf05dc9b06bd7bd566bd6c9e (diff)
downloadsystemd-bfde9421af1458e18999d787b1ab46a6a33e8bb6.tar.gz
systemd-bfde9421af1458e18999d787b1ab46a6a33e8bb6.tar.bz2
systemd-bfde9421af1458e18999d787b1ab46a6a33e8bb6.zip
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.
Diffstat (limited to 'src/udev/udevd.c')
-rw-r--r--src/udev/udevd.c21
1 files changed, 0 insertions, 21 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 0ae61c1e8b..144a20ec63 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -774,21 +774,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;
@@ -808,13 +794,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 */