]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: fix initial button state is not fetched when device is registered late (...
authorMorgan <me@morgan.kr>
Sun, 7 Dec 2025 00:48:49 +0000 (09:48 +0900)
committerGitHub <noreply@github.com>
Sun, 7 Dec 2025 00:48:49 +0000 (09:48 +0900)
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
src/login/logind.c
src/login/logind.h

index 1d88ec966131ee8ec47b75fa1046c8676f0e11b7..4962aa03087427d0420237b6f186ba16cee34542 100644 (file)
@@ -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,28 +343,39 @@ 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));
+                b = hashmap_get(m->buttons, sysname);
+                goto unwatch;
+        }
 
-        else {
-                const char *sn;
+        r = manager_add_button(m, sysname, &b);
+        if (r < 0)
+                return r;
+        bool is_new = r > 0;
 
-                r = manager_add_button(m, sysname, &b);
-                if (r < 0)
-                        return r;
+        const char *sn;
+        r = device_get_seat(d, &sn);
+        if (r < 0)
+                return r;
 
-                r = device_get_seat(d, &sn);
-                if (r < 0)
-                        return r;
+        button_set_seat(b, sn);
 
-                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;
 
-                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);
-        }
+        if (ret_button)
+                *ret_button = b;
+
+        return is_new;
+
+unwatch:
+        button_free(b);
+
+        if (ret_button)
+                *ret_button = NULL;
 
         return 0;
 }
index 5cdfc2a00dc8e3980c3a400f06c6995873e9ce2e..65bc854f4edccb6fe158ded9247e75b7837312a2 100644 (file)
@@ -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;
 }
 
index 332a59f6da67d9d84656002f045b3d4b7fec65af..4e3c15de52124797578e30cea5399c225e108128 100644 (file)
@@ -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);