]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
login: add device monitor instance to receive events for devices with uaccess tag
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 29 May 2025 01:22:21 +0000 (10:22 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 29 May 2025 02:41:25 +0000 (11:41 +0900)
With c960ca2be1cfd183675df581f049a0c022c1c802, logind triggers uevents
for devices with uaccess tag, and waits for the events being processed
by udevd.
However, logind received not all triggered events, and might lose some
events. That causes session and user state file not updated, and many
desktop environment application handled the session and user were inactive.

This introduces one more device monitor instance which monitor events
for devices with 'uaccess' tag. Hence, all triggered events will be
recieved by logind, and session and user state file will be updated.

Follow-up for c960ca2be1cfd183675df581f049a0c022c1c802.
Fixes #37579.

src/login/logind.c
src/login/logind.h

index 65c8d9913d18adad3fe396c4181a5c800a8208c2..93a1b66c3c4d16836de9c64cefbfe55d3cd61f8f 100644 (file)
@@ -152,6 +152,7 @@ static Manager* manager_free(Manager *m) {
         sd_device_monitor_unref(m->device_monitor);
         sd_device_monitor_unref(m->device_vcsa_monitor);
         sd_device_monitor_unref(m->device_button_monitor);
+        sd_device_monitor_unref(m->device_uaccess_monitor);
 
         if (m->unlink_nologin)
                 (void) unlink_or_warn("/run/nologin");
@@ -655,6 +656,35 @@ static int manager_dispatch_device_udev(sd_device_monitor *monitor, sd_device *d
         return 0;
 }
 
+static int manager_dispatch_uaccess_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) {
+        Manager *m = ASSERT_PTR(userdata);
+        int r;
+
+        assert(device);
+
+        /* If the device currently has "master-of-seat" tag, then it has been or will be processed by
+         * manager_dispatch_seat_udev(). */
+        r = sd_device_has_current_tag(device, "master-of-seat");
+        if (r < 0)
+                log_device_warning_errno(device, r, "Failed to check if the device currently has master-of-seat tag, ignoring: %m");
+        if (r != 0)
+                return 0;
+
+        /* If the device is in input, graphics, or drm, then the event has been or will be processed by
+         * manager_dispatch_device_udev(). */
+        r = device_in_subsystem(device, "input", "graphics", "drm");
+        if (r < 0)
+                log_device_warning_errno(device, r, "Failed to check device subsystem, ignoring: %m");
+        if (r != 0)
+                return 0;
+
+        r = manager_process_device_triggered_by_seat(m, device);
+        if (r < 0)
+                log_device_warning_errno(device, r, "Failed to process seat device event triggered by us, ignoring: %m");
+
+        return 0;
+}
+
 static int manager_dispatch_vcsa_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) {
         Manager *m = ASSERT_PTR(userdata);
         int r;
@@ -893,6 +923,7 @@ static int manager_connect_udev(Manager *m) {
         assert(m);
         assert(!m->device_seat_monitor);
         assert(!m->device_monitor);
+        assert(!m->device_uaccess_monitor);
         assert(!m->device_vcsa_monitor);
         assert(!m->device_button_monitor);
 
@@ -934,6 +965,24 @@ static int manager_connect_udev(Manager *m) {
 
         (void) sd_device_monitor_set_description(m->device_monitor, "input,graphics,drm");
 
+        r = sd_device_monitor_new(&m->device_uaccess_monitor);
+        if (r < 0)
+                return r;
+
+        r = sd_device_monitor_filter_add_match_tag(m->device_uaccess_monitor, "uaccess");
+        if (r < 0)
+                return r;
+
+        r = sd_device_monitor_attach_event(m->device_uaccess_monitor, m->event);
+        if (r < 0)
+                return r;
+
+        r = sd_device_monitor_start(m->device_uaccess_monitor, manager_dispatch_uaccess_udev, m);
+        if (r < 0)
+                return r;
+
+        (void) sd_device_monitor_set_description(m->device_uaccess_monitor, "uaccess");
+
         /* Don't watch keys if nobody cares */
         if (!manager_all_buttons_ignored(m)) {
                 r = sd_device_monitor_new(&m->device_button_monitor);
index d7b5b24854108e5e8e63dd9f64483d905f8ff750..6a46374e8ace3000c9c114e524671fc10eb03b41 100644 (file)
@@ -25,7 +25,11 @@ typedef struct Manager {
         LIST_HEAD(Session, session_gc_queue);
         LIST_HEAD(User, user_gc_queue);
 
-        sd_device_monitor *device_seat_monitor, *device_monitor, *device_vcsa_monitor, *device_button_monitor;
+        sd_device_monitor *device_seat_monitor;
+        sd_device_monitor *device_monitor;
+        sd_device_monitor *device_vcsa_monitor;
+        sd_device_monitor *device_button_monitor;
+        sd_device_monitor *device_uaccess_monitor;
 
         sd_event_source *console_active_event_source;