From 392b9ab6472f279c13f0100ad77f0365284aa8b2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 29 May 2025 10:22:21 +0900 Subject: [PATCH 1/2] login: add device monitor instance to receive events for devices with uaccess tag 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 | 49 ++++++++++++++++++++++++++++++++++++++++++++++ src/login/logind.h | 6 +++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/login/logind.c b/src/login/logind.c index 65c8d9913d..93a1b66c3c 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -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); diff --git a/src/login/logind.h b/src/login/logind.h index d7b5b24854..6a46374e8a 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -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; From 50e518a96a38fd7d9990b16b89ead8b858fa4e52 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 29 May 2025 11:05:29 +0900 Subject: [PATCH 2/2] login: add several debugging logs about synthetic events --- src/login/logind-seat.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index cfc3dd1bf1..db476af251 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -30,6 +30,7 @@ #include "string-util.h" #include "terminal-util.h" #include "tmpfile-util.h" +#include "udev-util.h" #include "user-record.h" int seat_new(Manager *m, const char *id, Seat **ret) { @@ -205,8 +206,10 @@ int seat_preallocate_vts(Seat *s) { static void seat_triggered_uevents_done(Seat *s) { assert(s); - if (!set_isempty(s->uevents)) + if (!set_isempty(s->uevents)) { + log_debug("%s: waiting for %u events being processed by udevd.", s->id, set_size(s->uevents)); return; + } Session *session = s->active; @@ -244,6 +247,7 @@ int manager_process_device_triggered_by_seat(Manager *m, sd_device *dev) { if (!s) return 0; + log_device_uevent(dev, "Received event processed by udevd"); free(ASSERT_PTR(set_remove(s->uevents, &uuid))); seat_triggered_uevents_done(s); @@ -306,6 +310,8 @@ static int seat_trigger_devices(Seat *s) { continue; } + log_device_debug(d, "Triggered synthetic event (ACTION=change, UUID=%s).", SD_ID128_TO_UUID_STRING(uuid)); + _cleanup_free_ sd_id128_t *copy = newdup(sd_id128_t, &uuid, 1); if (!copy) return -ENOMEM;