Skip to content

fix: lock on logind Lock and before sleep - #39

Open
perlowja wants to merge 1 commit into
singularityos-lab:mainfrom
perlowja:pr/logind-lock-and-sleep-20261014
Open

perlowja wants to merge 1 commit into
singularityos-lab:mainfrom
perlowja:pr/logind-lock-and-sleep-20261014

Conversation

@perlowja

Copy link
Copy Markdown
Contributor

loginctl lock-session sends Session.Lock to the session, and a suspend started outside the shell (systemctl suspend, a logind lid or idle action) sends PrepareForSleep. The shell handled neither: lock-session did nothing, and lock-on-suspend only worked when the shell itself started the suspend.

The shell now follows Lock for its own logind session (sender checked) and locks through PowerActions.lock_screen(), the same path as the shortcut and the idle lock. It holds a logind "sleep" delay inhibitor; on PrepareForSleep it locks when lock-on-suspend is on and releases the inhibitor once the lock screen is up (at most 3 s, so a lock screen that never comes up cannot block sleep). With lock-on-suspend off, or when already locked, the inhibitor is released at once. Repeated requests are ignored, and Unlock is ignored so a lock stays until the user authenticates.

Before (main, on hardware): loginctl lock-session left the session unlocked and no lock client started; systemctl suspend slept with the desktop unlocked.

After (the same change carried in our desktop build, on an amd64 laptop and an arm64 desktop):

  • loginctl lock-session: lock screen up in about 225 ms; a second lock-session while locked starts no second client; loginctl unlock-session leaves it locked; wrong password stays locked, right password unlocks; a new lock-session after unlock locks again.
  • systemctl suspend with lock-on-suspend on: locked about 230 ms after PrepareForSleep, sleep.target reached about 0.6 s later.
  • Real suspend with an RTC wake (laptop): the session was locked before sleep and asked for the password on resume.

tests/logind_lock_test.vala (meson test logind-lock) runs the listener against a fake logind on a private bus: session resolution (XDG_SESSION_ID, by PID, user display, none), Lock, repeated Lock, Unlock, sleep with lock-on-suspend on/off, already locked, a lock screen that never comes up, and inhibitor re-take after resume. On Debian forky: ninja builds, meson test 83 of 85 pass including logind-lock (34 checks); parental-helper and crash-handler fail the same way on main in a container.

AI assistance: disclosed

`loginctl lock-session` emits Session.Lock on the session object, and a
suspend started outside the shell (systemctl suspend, a logind lid or
idle action) emits PrepareForSleep. The shell listened to neither, so
lock-session did nothing and lock-on-suspend only applied when the shell
itself suspended.

Follow both for the shell's own session, with logind as the sender. Lock
goes through PowerActions.lock_screen(). Before sleep a "sleep" delay
inhibitor is released once the lock screen is up (at most 3 s), or at
once when lock-on-suspend is off or the session is already locked.
Repeated requests are no-ops; Unlock is ignored.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: Wrote the logind Lock/PrepareForSleep listener, its delay-inhibitor handling and the GTestDBus unit test against a fake logind, from a report that loginctl lock-session was ignored; reviewed and tested on hardware by the author.
@perlowja

Copy link
Copy Markdown
Contributor Author

@mirkobrombin for review when you have a moment. This gives the existing lock-on-suspend key a consumer for suspends that do not come from the shell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant