Skip to content

fix: give connect attempts an identity so stale failures can't clobber newer ones - #102

Merged
MegaManSec merged 1 commit into
mainfrom
fix/connect-attempt-identity
Aug 7, 2026
Merged

fix: give connect attempts an identity so stale failures can't clobber newer ones#102
MegaManSec merged 1 commit into
mainfrom
fix/connect-attempt-identity

Conversation

@MegaManSec

Copy link
Copy Markdown
Owner

From the adversarial review sweep (confirmed finding). Connect bookkeeping (pair watchdog, announce flag, result waiters, row state) is keyed by address alone, and overlapping attempts are reachable: a silent watcher/adoption retry can still be dying — up to the 60s watchdog — when a peer command starts a fresh attempt for the same address. The stale attempt's late failure then cancelled the new attempt's watchdog, consumed its announce flag, flipped its row to disconnected, and failed its waiters — acking OP_FAILED mid-handoff so the sender rolled back while the receiver's attempt kept running, leaving both Macs fighting over the set.

Every attempt now mints a monotonic token; failure paths carry theirs and no-op once superseded. Three refinements from the review of the first draft: the pair delegate fails with the pair's own token (recorded at install — the address's current token can belong to a newer attempt that hasn't installed its pair yet), token recording is newest-wins across threads, and a pairing success stays terminal-good — it opens and adopts the connection even if its attempt was superseded or its watchdog fired a beat earlier (the pre-token code recovered that race, and now it still does).

Stacked on #99 (fix/bug-sweep) — merge that first, then retarget this to main.

Test: normal single connect/release/take unaffected; take a peripheral from the peer while a watcher retry is mid-flight against a stuck device (the take must survive the retry's death: no spurious "Pairing Failed", no OP_FAILED rollback); a genuinely stuck device still times out with one announced "Pairing Timed Out". Typechecked here; please build before merging.

…r newer ones

Connect bookkeeping (watchdog, announce flag, result waiters) is keyed by
address alone, and overlapping attempts are reachable: a silent watcher
retry can still be dying — up to the 60s pair watchdog — when a peer
command starts a fresh attempt for the same address. Its late failure then
cancelled the new attempt's watchdog, consumed its announce flag, and
failed its waiters (acking OP_FAILED mid-handoff, so the sender rolled
back while the receiver's attempt continued).

Failure paths now carry an attempt token and no-op once superseded. The
pair delegate keys failures on the pair's own token (recorded when the
pair is installed — the address's current token could belong to a newer
attempt that hasn't installed its pair yet), token recording is
newest-wins across threads, and a pairing success stays terminal-good:
it opens and adopts the connection even when its attempt was superseded
or its watchdog fired a beat earlier.
@MegaManSec
MegaManSec force-pushed the fix/connect-attempt-identity branch from d2f4556 to 5478640 Compare August 7, 2026 06:59
@MegaManSec MegaManSec changed the title Give connect attempts an identity so stale failures can't clobber newer ones fix: give connect attempts an identity so stale failures can't clobber newer ones Aug 7, 2026
@MegaManSec
MegaManSec merged commit 2dc559c into main Aug 7, 2026
2 checks passed
@MegaManSec
MegaManSec deleted the fix/connect-attempt-identity branch August 7, 2026 07:03
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.25.4 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant