]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: create /run/udev/queue file earlier 40518/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 30 Jan 2026 11:32:15 +0000 (20:32 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 3 Feb 2026 12:25:01 +0000 (21:25 +0900)
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.

src/udev/udev-manager.c
src/udev/udev-manager.h
src/udev/udev-watch.c

index a62af149db8f165528025b666ad99f139d00cf83..2e52a367a8d2ed0e716cf79a7f6e06d2e907f41b 100644 (file)
@@ -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);
 
index 6c4469ce735b31469e19a026f0197acfe5bdece2..2eaaf5b0c3d5757a9cefdf47c1cd5e1094bc8166 100644 (file)
@@ -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);
index 3f4aa37dec9af996aaf56a1cfc98447051997fef..7cb34edbf6aa5514e164de1ea59f411ae2f09a96 100644 (file)
@@ -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;