fix(sync): recover from a locked keyring without restarting the app - #215
Merged
Merged
Conversation
…loses #214) When the Secret Service restarts (e.g. gnome-keyring-daemon crashing outside the PAM phase), its collections come back locked and the app parks in the keyring-locked state. Issue #170's capped retry exhausts long before the user unlocks the keyring, and afterwards nothing re-checks the credentials: new triggers either never arrive (push-ready configs drop the remote interval) or bounce off the parked state, so only relaunching the app recovered. Two complementary changes: - The engine now attempts to unlock the locked collections via the Secret Service when a lookup reports Locked, then retries the lookup once. GNOME collections created by the desktop session share the login password, so the service completes the unlock prompt on its own while the client connection stays alive: the common case heals with no user interaction. - Once #170's fast backoff budget is exhausted, the scheduler falls back to a slow periodic keyring watch (60 s, uncapped, like the server probe of #179) that re-enters the engine until a run resolves credentials, so the folder also recovers when the keyring is unlocked by any other means. No new visible states or strings.
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.
Problem
When the system Secret Service restarts (e.g. gnome-keyring-daemon crashing outside the PAM phase), its collections come back Locked. The app reports "the password keyring is locked", #170's capped retry (5 attempts over ~1 min) exhausts long before the keyring is unlocked, and afterwards nothing re-checks the credentials: in push-ready configs the remote interval is dropped (#185), other triggers just queue up, and the parked folder never retries on its own. Only relaunching the app recovered.
Verified today on a live session: with a persistent D-Bus connection,
Secret.Service.unlock(collections)unlocks both theloginand the default collection without prompting (they share the login password), so an in-app unlock attempt is viable.Fix
Two complementary changes, both minimal:
Locked, the engine asks the source to unlock the locked collections and retries the lookup once.CredentialsStore::unlock_locked_collections()iterates all collections and unlocks the locked ones; the crate's blocking client keeps its connection alive through the prompt, which is exactly what gnome-keyring needs to auto-complete it. The common case (session-keyring collections) heals with no user interaction.No new UI states, no new translated strings.
Tests
keyring_retry_budget_is_capped_and_falls_back_to_a_watch(updated) andkeyring_watch_recovers_without_restart_once_unlocked: after the fast budget is exhausted the watch keeps re-entering the engine and a later successful run recovers to IdleOk with no restart.locked_lookup_retries_once_after_a_successful_unlockandlocked_lookup_without_unlock_is_not_retried: engine-level, with injectable credential sources (no real keyring).Closes #214