From 1bd2acf1936c78593073a8365b035753f1f4eb7e Mon Sep 17 00:00:00 2001 From: Rocker Zhang Date: Thu, 21 May 2026 18:29:24 +0800 Subject: [PATCH] test: cover lingering users surviving a soft-reboot in TEST-82 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression coverage for the soft-reboot linger bug fixed in 9f25feb4ed18 ("logind: keep lingering users at startup-time GC", #41789): a lingering user's user@.service was started after a hardware reboot but not after `systemctl soft-reboot`, because logind GC'd the user at startup before user_start() ran. On the first boot, enable lingering for the pre-existing testuser and wait for its user@UID.service to come up. After the first soft-reboot (which keeps the same persistent rootfs), assert the service is active again — this is the regression check. Disable lingering again before the nextroot switch in the second boot so the lingering user doesn't leak into the later boots' minimal overlay rootfs. Verified locally in a qemu/KVM VM: passes with the fix present, and with the fix reverted the second-boot assertion times out (the lingering user is GC'd in logind startup and user@UID.service never comes back), confirming the test exercises the bug. Co-developed-by: Claude Opus 4.7 --- test/units/TEST-82-SOFTREBOOT.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/units/TEST-82-SOFTREBOOT.sh b/test/units/TEST-82-SOFTREBOOT.sh index 03f6b78e57..778bdbd7f8 100755 --- a/test/units/TEST-82-SOFTREBOOT.sh +++ b/test/units/TEST-82-SOFTREBOOT.sh @@ -190,6 +190,17 @@ elif [ -f /run/TEST-82-SOFTREBOOT.touch ]; then test "$(systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive-sigterm.service)" != "active" test "$(systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive.service)" != "active" + # Regression test for #41789: the lingering user enabled on the first boot must + # have its user@.service started again after the soft reboot. Before the fix it + # was GC'd at logind startup and never restarted. Disable lingering again here, + # before the nextroot switch below (the third boot runs on a minimal overlay + # rootfs that does not have this user). terminate-user is best-effort: it can + # race the asynchronous disable-linger/UserStopDelaySec teardown. + linger_uid=$(id -u testuser) + timeout 30 bash -c "until systemctl is-active --quiet user@${linger_uid}.service; do sleep 1; done" + loginctl disable-linger testuser + loginctl terminate-user testuser || true + # This time we test the /run/nextroot/ root switching logic. (We synthesize a new rootfs from the old via overlayfs) mkdir -p /run/nextroot /tmp/nextroot-lower /original-root mount -t tmpfs tmpfs /tmp/nextroot-lower @@ -313,6 +324,18 @@ EOF systemd-run --wait false || true done + # Regression test for #41789: a lingering user's user@.service must come back + # after a soft reboot, the same way it does after a hardware reboot. It used + # to be garbage-collected at logind startup (before user_start() ran), because + # /run/systemd/users is preserved across soft-reboot and fed the user into the + # GC queue while its units were not active yet. Enable lingering for the + # pre-existing testuser here; the second boot asserts the service is active + # again. testuser lives in the persistent rootfs, so it survives the + # (non-nextroot) soft reboot into the second boot. + loginctl enable-linger testuser + linger_uid=$(id -u testuser) + timeout 30 bash -c "until systemctl is-active --quiet user@${linger_uid}.service; do sleep 1; done" + trigger_uevent # Now issue the soft reboot. We should be right back soon.