From: Yu Watanabe Date: Fri, 30 Jan 2026 11:32:15 +0000 (+0900) Subject: udev: create /run/udev/queue file earlier X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc709eff0bc956df7f1c311006b319eae8bc8f1f;p=thirdparty%2Fsystemd.git udev: create /run/udev/queue file earlier When udevd received a uevent or inotify event, we will queue or trigger synthesized events. To minimize the race between processing these events by udevd and user invocation of 'udevadm settle', let's create /run/udev/queue file earlier. On some errors, no event may be queued, but in that case, the file will be removed by the post event source if nothing queued. See on_post(). Hopefully mitigate the issue #40499. --- diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index a62af149db8..2e52a367a8d 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -969,14 +969,6 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { TAKE_PTR(event); log_device_uevent(dev, "Device is queued"); - if (!manager->queue_file_created) { - r = touch("/run/udev/queue"); - if (r < 0) - log_warning_errno(r, "Failed to touch /run/udev/queue, ignoring: %m"); - else - manager->queue_file_created = true; - } - return 0; } @@ -1075,6 +1067,9 @@ static int manager_deserialize_events(Manager *manager, int *fd) { n++; } + if (n > 0) + (void) manager_create_queue_file(manager); + log_debug("Deserialized %"PRIu64" events.", n); return 0; } @@ -1085,6 +1080,8 @@ static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata) DEVICE_TRACE_POINT(kernel_uevent_received, dev); + (void) manager_create_queue_file(manager); + device_ensure_usec_initialized(dev, NULL); r = event_queue_insert(manager, dev); @@ -1263,6 +1260,22 @@ static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void return 1; } +int manager_create_queue_file(Manager *manager) { + int r; + + assert(manager); + + if (manager->queue_file_created) + return 0; + + r = touch("/run/udev/queue"); + if (r < 0) + return log_warning_errno(r, "Failed to touch /run/udev/queue: %m"); + + manager->queue_file_created = true; + return 0; +} + static int manager_unlink_queue_file(Manager *manager) { assert(manager); diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h index 6c4469ce735..2eaaf5b0c3d 100644 --- a/src/udev/udev-manager.h +++ b/src/udev/udev-manager.h @@ -93,3 +93,5 @@ int manager_reset_kill_workers_timer(Manager *manager); bool devpath_conflict(const char *a, const char *b); int manager_requeue_locked_events_by_device(Manager *manager, sd_device *dev); + +int manager_create_queue_file(Manager *manager); diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c index 3f4aa37dec9..7cb34edbf6a 100644 --- a/src/udev/udev-watch.c +++ b/src/udev/udev-watch.c @@ -290,6 +290,7 @@ static int manager_process_inotify(Manager *manager, const struct inotify_event log_device_debug(dev, "Received inotify event of watch handle %i.", e->wd); + (void) manager_create_queue_file(manager); (void) manager_requeue_locked_events_by_device(manager, dev); (void) synthesize_change(manager, dev); return 0;