fix(visaged): handle SIGTERM (closes #26)#30
Merged
Conversation
`tokio::signal::ctrl_c()` is SIGINT-only on Unix. systemd's `systemctl stop`/`systemctl restart` sends SIGTERM, which visaged was ignoring — systemd then waited the default `TimeoutStopSec=90s` before escalating to SIGKILL, manifesting as the ~90s hang reported in issue #26 after `visage-resume.service` restarts the daemon post-hibernate. Install handlers for both SIGINT and SIGTERM via `tokio::signal::unix::signal` and `tokio::select!`, matching the pattern used elsewhere in our daemons (e.g. `esver-capture-cli`). Also adds `TimeoutStopSec=10s` to `visaged.service` as defense in depth for the edge case where a v4l2 capture is mid-flight on shutdown — for example a stale camera fd after hibernate resume that isn't promptly interruptible. Brings the worst-case `systemctl restart` from ~90s to ~10s instead of the prior default-90s SIGKILL escalation. CHANGELOG entry added under `[Unreleased] > Fixed`.
This was referenced May 28, 2026
CI flagged the prior commit's binding shape. rustfmt prefers the binding name on its own line when the value-expression spans the column budget. No semantic change.
This was referenced May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #26 —
systemctl restart visaged.servicehangs for ~90s after hibernate resume becausevisagedignores SIGTERM.Root cause
crates/visaged/src/main.rs:91usedtokio::signal::ctrl_c().await?for shutdown. On Unix,tokio::signal::ctrl_c()is SIGINT-only. systemd'ssystemctl stop/systemctl restartsends SIGTERM, which the daemon has no handler for — so systemd waits the defaultTimeoutStopSec=90sbefore escalating to SIGKILL. Reported as the ~90s window during which face auth doesn't work aftervisage-resume.servicefires.Note: this is independent of the stale-camera-fd concern in the original report. The fd may indeed go bad across hibernate, but the user-visible 90s hang is entirely on the signal-handling side — we never reach any shutdown / fd-teardown path.
Fix
Two changes:
crates/visaged/src/main.rs— install handlers for both SIGINT and SIGTERM viatokio::signal::unix::signal(SignalKind::terminate())+SignalKind::interrupt(), awaited in atokio::select!. Matches the pattern used in our other daemons (e.g.esver-capture-cli'swait_for_shutdown_signal).packaging/systemd/visaged.service— addTimeoutStopSec=10sas defense in depth, in case a v4l2 capture is mid-flight and not promptly interruptible (e.g. a stale camera fd on hibernate resume that the v4l ioctl can't immediately abort).Verification
rx.blocking_recv()(crates/visaged/src/engine.rs:166); whenmainreturns and the tokio runtime drops, the channel sender drops, the engine thread exits cleanly. No new shutdown plumbing required.systemctl restartgoes from ~90s → ~10s for the rare case where the capture loop genuinely can't unwind in time.cargo checkblocked on a devshell gap (missinglibclangforv4l2-sysbindgen, missingrustfmt/clippy) — CI will run all gates. I'll file a separate PR to round out the devshell.Test plan
cargo fmt --all -- --checkcleancargo clippy --workspace -- -D warningscleancargo test --workspacegreenbuild-debproduces a.debcleanlysudo systemctl restart visaged.servicereturns in ~1s when idle (was ~1s before, should still be ~1s — sanity check)sudo systemctl restart visaged.servicereturns in ≤10s after hibernate resume (previously ~90s)CHANGELOG
Entry added under
[Unreleased] > Fixed. Will land in v0.3.2 per the release plan.🤖 Generated with Claude Code