Skip to content

fingerprint: rebuild device proxy and re-claim after waking from sleep - #1049

Open
PixelHegel wants to merge 1 commit into
hyprwm:mainfrom
PixelHegel:fix/fingerprint-resume-reclaim
Open

PixelHegel wants to merge 1 commit into
hyprwm:mainfrom
PixelHegel:fix/fingerprint-resume-reclaim

Conversation

@PixelHegel

Copy link
Copy Markdown

On machines where the fingerprint reader powers down during suspend (Synaptics Prometheus 06cb:00fc here, but any reader that re-enumerates on resume), fprintd's device object doesn't survive sleep. The claim hyprlock took before suspending is gone when the machine wakes up — and if a verify was still in flight when the system went down, fprintd can wedge badly enough that a restart is the only way to recover it, which also kills the claim.

The wake side of the PrepareForSleep handler currently just calls startVerify(), which sees the old device proxy and goes straight to VerifyStart. That fails with Device was not claimed before use, we log a warning, and that's the end of it — fingerprint auth is dead until hyprlock itself restarts. In practice: lock, close the lid, open it, and only the password works.

This treats post-sleep state as stale instead. On wake we stop verification and release whatever claim we held (both helpers already swallow errors, which is exactly what we want when the daemon was restarted underneath us), drop the proxy, and let startVerify() take its existing cold-start path: GetDefaultDevice, resubscribe the signals, claim, verify.

The release-before-reclaim order keeps readers that do survive suspend working: there the release succeeds and we simply claim again.

Tested on Arch (fprintd 1.94.5, libfprint 1.94.10) with the Prometheus sensor: fingerprint used to be dead after every single lid-close cycle, and comes back reliably with this patch.

🤖 Generated with Claude Code

On resume the handler called startVerify() on the pre-sleep device proxy,
which goes straight to VerifyStart. That only works if fprintd kept both
the device object and our claim across sleep. Readers that power down
during sleep re-enumerate on resume (e.g. Synaptics Prometheus 06cb:00fc),
which tears down fprintd's device object — and wedges fprintd badly enough
that restarting it is the only recovery, at which point the claim is gone
too. VerifyStart then fails with "Device was not claimed before use" and
fingerprint auth stays dead until hyprlock itself restarts.

Instead, treat post-sleep state as untrustworthy: stop verification and
release whatever claim we held (both already swallow errors, which is
exactly right when the daemon was restarted), drop the proxy, and let
startVerify() take its existing cold-start path — re-query the default
device, re-subscribe the signals, claim, verify.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sudosteve

Copy link
Copy Markdown

I've been seeing the same issue on my thinkpad and debugging with Claude. Does this actually fully resolve the issue for you? What about when you close the lid for more than 20 minutes? My claude developed a fix that is a "superset" of this one that addresses longer lid closes in a way this does not:

Findings from fprintd (G_MESSAGES_DEBUG=all) and hyprlock --verbose logs on a Synaptics Prometheus 06cb:00fc, fprintd 1.94.5 / libfprint 1.94.100, hyprlock 0.9.6:

  1. The reader only re-enumerates after long suspends. Short lid closes give a USB reset and the old device object still works; longer ones give a disconnect and a new device object. The wake path needs to handle both.
  2. Claiming at the instant of PrepareForSleep(false) is too early. fprintd probes the new device ~1 s after resume, so an immediate claim gets the old object and fails with Device was already claimed. A ~2.5 s delay plus retries fixes this.
  3. VerifyStop/Release on the old object never return. The synaptics driver can't cancel a verify on a vanished USB device and fprintd's Release handler blocks forever in a nested main loop. With the default sdbus timeout, the synchronous stop + release in this PR would stall hyprlock for up to 50 s after wake. Those calls need a short timeout, and Release should be skipped when the device is stale. fprintd also keeps the stale object exported and permanently claimed, and GetDefaultDevice is just "last in list", so GetDevices with rotation on failure is more robust.
  4. A VerifyStop at PrepareForSleep(true) is required, but must be asynchronous. Despite fingerprint: allow fprint to suspend and cancel verify for us #722: libfprint's synaptics driver re-submits its interrupt transfer with a NULL cancellable, so fprintd's own device suspend can't complete on its own. A client VerifyStop makes the driver send a cancel command, the sensor answers, and the suspend finishes. Without it logind times out the inhibitor after 5 s, the sensor sleeps mid-scan, and it returns error 101 to everything until re-opened. The reply to that VerifyStop arrives after resume or never, so it can't be a blocking call.
  5. fprintd reports a cancelled verify as verify-no-match. That late status must be ignored or it burns one of the three retries.

With all five, a "lock first, close lid 24 min, reader re-enumerates on wake" cycle recovers about 3 s after resume; the reset-only case keeps its claim and just restarts verification. The terminate() fix from #1068 is subsumed since the proxy is always reset.

@sudosteve

Copy link
Copy Markdown

Also I've noticed no engagement with this PR from any maintainers. Is it just people being focused on other things or is it just the lack of non-AI contribution to the code or request comments keeping everyone from taking it seriously? In other words, do y'all need me to put some more legwork into understanding the claude generated fix and properly endorsing/explaining it, or can we all just agree, if I say a fix fixes it for me, then let's get it merged.

The above fix doesn't fix it for me but I have a fix that was similarly generate by claude that does.

@sudosteve

Copy link
Copy Markdown

#1066 Has the retry logic that is needed and included in my fix. I'll work on submitting my own pull request.

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.

2 participants