Merge pull request 'blankpad has had no screen lock for 8 days; the lid suspends it unlocked' (#48) from fix/47-lock-watcher-resilience into main
This commit was merged in pull request #48.
This commit is contained in:
@@ -2,6 +2,13 @@
|
||||
Description=swayidle idle lock (locks via noctalia-shell IPC, suspends on lid)
|
||||
Documentation=https://github.com/swaywm/swayidle
|
||||
After=graphical-session.target
|
||||
# Restart together with the session, not merely at boot: this unit is wanted by
|
||||
# default.target, so a compositor restart used to leave it orphaned while the target came
|
||||
# back without it. Refs #47.
|
||||
PartOf=graphical-session.target
|
||||
# With Restart=always below, a fast failure loop must never wedge the watcher into `failed`:
|
||||
# a lock that keeps trying beats a lock that stopped trying. Refs #47.
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
# Locks via the noctalia v5 shell; `noctalia msg` resolves the running instance
|
||||
@@ -11,7 +18,10 @@ ExecStart=/usr/bin/swayidle -w \
|
||||
timeout 300 '/usr/bin/noctalia msg session lock' \
|
||||
before-sleep '/usr/bin/noctalia msg session lock' \
|
||||
after-resume '/usr/bin/noctalia msg session lock'
|
||||
Restart=on-failure
|
||||
# `swayidle -w` exits 0 on SIGTERM, and that is how this watcher died on 2026-10-12: a clean
|
||||
# exit that `Restart=on-failure` cannot see, leaving the box unlocked for a week. A supervisor
|
||||
# restarts always. Refs #47.
|
||||
Restart=always
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -205,3 +205,33 @@ it in the other. Re-dump on the box whose settings are canonical (`dconf dump /
|
||||
dotfiles/dconf/dump.txt`), then delete the state sections before committing — the census's
|
||||
*Never track: app state* class applies inside a tracked file, not just to whole directories.
|
||||
Refs #44.
|
||||
|
||||
## Law: a watcher must restart on a clean exit too
|
||||
|
||||
`swayidle-lock.service` was `enabled`, present in `default.target.wants/`, and **dead for eight
|
||||
days**: `Result=success`, `NRestarts=0`, gone since 2026-10-12 16:22 after 2d 21h of uptime.
|
||||
`Restart=on-failure` cannot see a clean exit, and `swayidle -w` exits 0 on SIGTERM — so the
|
||||
watcher that owns the 5-minute idle lock *and* the `before-sleep` lock quietly stopped existing,
|
||||
and nothing noticed. With it dead and logind at `HandleLidSwitch=suspend`, closing the lid
|
||||
suspended the machine **unlocked**: the lock hook lived inside the thing that had died. No
|
||||
alternative existed — `pgrep -c -u blankpad 'swayidle|swaylock|hyprlock|gtklock'` = 0, and neither
|
||||
`autostart.kdl` launches a locker.
|
||||
|
||||
Three settings, each with a job: `Restart=always`, because a supervisor must not assume it can
|
||||
only die badly; `StartLimitIntervalSec=0`, because a fast loop must never wedge it into `failed` —
|
||||
a lock that keeps trying beats one that stopped trying; and `PartOf=graphical-session.target`,
|
||||
because the unit is wanted by `default.target`, so the session coming back did not bring *it*
|
||||
back.
|
||||
|
||||
Verify by behaviour rather than by reading the file — the point is surviving the event that killed
|
||||
it in October:
|
||||
|
||||
```bash
|
||||
systemctl --user start swayidle-lock.service
|
||||
kill -TERM "$(systemctl --user show swayidle-lock.service -p MainPID --value)"
|
||||
sleep 8 && systemctl --user show swayidle-lock.service -p NRestarts -p MainPID -p ActiveState
|
||||
```
|
||||
|
||||
The general shape: `deploy.sh` only ever *enables*. Nothing on any box re-checks that a unit the
|
||||
system depends on is still running, so a security posture can lapse silently and stay lapsed for a
|
||||
week. A liveness check for this tier belongs in the heartbeat, not in a human's memory. Refs #47.
|
||||
|
||||
Reference in New Issue
Block a user