From 97887d09a82f82f9afd20f4ed32c725e48f0efca Mon Sep 17 00:00:00 2001 From: Morgan Date: Sun, 7 Dec 2025 09:48:49 +0900 Subject: [PATCH] logind: fix initial button state is not fetched when device is registered late (#39978) If buttons that are not initialized from manager_startup() due to still being processed by udev, the initial state is not checked. (commit 405be62f05d76f1845f347737b5972158c79dd3e) This caused a problem which initial "close" state being not recognized if lid switch of some system getting initialized later. --- src/login/logind-core.c | 58 +++++++++++++++++++++++++---------------- src/login/logind.c | 7 +++-- src/login/logind.h | 2 +- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 1d88ec9661..4962aa0308 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -244,11 +244,14 @@ int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret) { int manager_add_button(Manager *m, const char *name, Button **ret_button) { Button *b; + bool is_new; assert(m); assert(name); b = hashmap_get(m->buttons, name); + is_new = !b; + if (!b) { b = button_new(m, name); if (!b) @@ -258,7 +261,7 @@ int manager_add_button(Manager *m, const char *name, Button **ret_button) { if (ret_button) *ret_button = b; - return 0; + return is_new; } int manager_process_seat_device(Manager *m, sd_device *d) { @@ -328,7 +331,7 @@ int manager_process_seat_device(Manager *m, sd_device *d) { return 0; } -int manager_process_button_device(Manager *m, sd_device *d) { +int manager_process_button_device(Manager *m, sd_device *d, Button **ret_button) { const char *sysname; Button *b; int r; @@ -340,29 +343,40 @@ int manager_process_button_device(Manager *m, sd_device *d) { return r; if (device_for_action(d, SD_DEVICE_REMOVE) || - sd_device_has_current_tag(d, "power-switch") <= 0) + sd_device_has_current_tag(d, "power-switch") <= 0) { - button_free(hashmap_get(m->buttons, sysname)); - - else { - const char *sn; - - r = manager_add_button(m, sysname, &b); - if (r < 0) - return r; - - r = device_get_seat(d, &sn); - if (r < 0) - return r; - - button_set_seat(b, sn); - - r = button_open(b); - if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error - * opening the device?) let's close the button again. */ - button_free(b); + b = hashmap_get(m->buttons, sysname); + goto unwatch; } + r = manager_add_button(m, sysname, &b); + if (r < 0) + return r; + bool is_new = r > 0; + + const char *sn; + r = device_get_seat(d, &sn); + if (r < 0) + return r; + + button_set_seat(b, sn); + + r = button_open(b); + if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error + * opening the device?) let's close the button again. */ + goto unwatch; + + if (ret_button) + *ret_button = b; + + return is_new; + +unwatch: + button_free(b); + + if (ret_button) + *ret_button = NULL; + return 0; } diff --git a/src/login/logind.c b/src/login/logind.c index 5cdfc2a00d..65bc854f4e 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -236,7 +236,7 @@ static int manager_enumerate_buttons(Manager *m) { FOREACH_DEVICE(e, d) { if (device_is_processed(d) <= 0) continue; - RET_GATHER(r, manager_process_button_device(m, d)); + RET_GATHER(r, manager_process_button_device(m, d, /* ret_button= */ NULL)); } return r; @@ -739,10 +739,13 @@ static int manager_dispatch_vcsa_udev(sd_device_monitor *monitor, sd_device *dev static int manager_dispatch_button_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) { Manager *m = ASSERT_PTR(userdata); + Button *b; assert(device); - manager_process_button_device(m, device); + if (manager_process_button_device(m, device, &b) > 0) + (void) button_check_switches(b); + return 0; } diff --git a/src/login/logind.h b/src/login/logind.h index 332a59f6da..4e3c15de52 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -153,7 +153,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **ret_user); int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret_inhibitor); int manager_process_seat_device(Manager *m, sd_device *d); -int manager_process_button_device(Manager *m, sd_device *d); +int manager_process_button_device(Manager *m, sd_device *d, Button **ret_button); int manager_spawn_autovt(Manager *m, unsigned vtnr);