From 658db799e77c8dc6dac4231ab0fc66603e06ec90 Mon Sep 17 00:00:00 2001 From: pixelhegel Date: Sun, 12 Jul 2026 22:55:10 +0400 Subject: [PATCH] fingerprint: rebuild device proxy and re-claim after waking from sleep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/auth/Fingerprint.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/auth/Fingerprint.cpp b/src/auth/Fingerprint.cpp index 48d2b953..0cf3ca34 100644 --- a/src/auth/Fingerprint.cpp +++ b/src/auth/Fingerprint.cpp @@ -71,8 +71,20 @@ void CFingerprint::init() { g_dbus->m_freedesktopLogin1->uponSignal("PrepareForSleep").onInterface(LOGIN_MANAGER).call([this](bool start) { Log::logger->log(Log::INFO, "fprint: PrepareForSleep (start: {})", start); m_sDBUSState.sleeping = start; - if (!m_sDBUSState.sleeping && !m_sDBUSState.verifying) - startVerify(); + if (m_sDBUSState.sleeping) + return; + + // Some readers power down during sleep and re-enumerate on resume, and + // fprintd may have been restarted, so the pre-sleep claim (and even the + // device object path) may no longer exist. Release whatever we held — + // ignoring failures — and rebuild the proxy so startVerify() re-queries + // the device and claims it again. + if (m_sDBUSState.device) { + stopVerify(); + releaseDevice(); + m_sDBUSState.device.reset(); + } + startVerify(); }); }