Repository navigation
Escape uncreatable socket state directory to /tmp; dedupe listener-failure captures per episode - #11050
Conversation
…errno fidelity Machines whose ~/.local/state/cmux cannot be created (root-owned after a sudo install, or an I/O-erroring home volume) loop forever at stage create_lock_directory: the current fallback routes the stable default to a sibling inside the same uncreatable directory, and applies no fallback at all when path resolution already selected the user-scoped sibling (CMUXTERM-MACOS-2MHE/2FVF/25PE breadcrumbs show wake restarts at cmux-<uid>.sock with zero fallback crumbs). The transport also collapses Cocoa-domain mkdir errors to EIO, hiding the real errno in telemetry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-failure captures per episode A machine whose ~/.local/state/cmux cannot be created (root-owned after a sudo install, or an I/O-erroring home volume) never got a working socket listener: the bind fallback moved the shared stable path to the user-scoped sibling inside the same uncreatable directory, and applied no fallback at all when resolution had already picked the user-scoped path. Every wake/activation restart re-failed at create_lock_directory and re-captured to Sentry after each 60s cooldown window (~1400 events/day per wedged machine). Now both stable paths escape create_directory/create_lock_directory failures to the legacy /tmp per-user path, which the CLI already discovers, so the listener starts and the wake loop ends. mkdir failures surface the underlying POSIX errno instead of collapsing Cocoa-domain errors to EIO. Listener-failure captures are deduped by a stateful gate: once per (message|stage|path|errno) key per failure episode, reset when the listener starts successfully, and path.missing on debug-like bundle ids stays breadcrumb-only because dev cleanup scripts delete /tmp dev sockets and the path monitor self-heals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review. 📝 WalkthroughWalkthroughThe change updates socket fallback rules, preserves underlying POSIX errnos from wrapped directory errors, and replaces cooldown-based listener failure capture with thread-safe per-episode deduplication. Tests cover fallback paths, errno handling, deduplication, suppression, and episode reset. ChangesSocket listener handling
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to The change adds a bounded socket fallback and episode-based failure reporting to prevent repeated listener failures and telemetry floods. No actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant TerminalController
participant SocketListenerFailureCaptureGate
participant Sentry
TerminalController->>SocketListenerFailureCaptureGate: shouldCapture(message, stage, path, errnoCode)
SocketListenerFailureCaptureGate-->>TerminalController: capture decision
TerminalController->>Sentry: capture failure when permitted
TerminalController->>SocketListenerFailureCaptureGate: listenerDidStart()
SocketListenerFailureCaptureGate->>SocketListenerFailureCaptureGate: clear episode keys
Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 warning)
✅ Passed checks (23 passed)
Full details: Description checkExplanation The description is detailed, relevant, and explains the changes, rationale, testing, affected issues, and residual risk. It omits the template headings and does not include the review-trigger block, checklist, or behavior-change demo video. Full details: Docstring CoverageExplanation Docstring coverage is 52.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 7 files. (1 skipped: 1 too large.) Full details: Cmux Swift Actor IsolationExplanation No changed production code matches the stated actor-isolation failures. The new Full details: Cmux Swift Blocking RuntimeExplanation The production diff adds Resolution Replace Full details: Cmux Browser Automation Off-MainExplanation The full PR range changes only socket-listener policy, errno handling, failure capture, related tests, and listener wiring in Full details: Cmux Expensive Synchronous LoadExplanation The PR does not add or move an expensive synchronous agent-history load. Added production code only changes socket fallback/errno handling, adds an in-memory locked failure gate, and wires that gate into existing socket lifecycle callbacks. The added production lines contain no Full details: Cmux Cache Substitution CorrectnessExplanation PASS: The PR does not substitute a cache for an authoritative read. The production diff changes socket-path fallback, mkdir errno unwrapping, and Sentry failure deduplication. It does not modify persistence, history, undo, or snapshot read paths, and no changed production line introduces a cached value for those consumers. The cache-substitution correctness check is therefore inapplicable. Full details: Cmux No Hacky SleepsExplanation PASS: The pull request changes only Swift files, including production Swift sources and Swift tests. The custom check applies only to production TypeScript, JavaScript, shell, and build/runtime scripts. The PR introduces no covered non-Swift files or delay constructs. Full details: Cmux Algorithmic ComplexityExplanation No algorithmic-complexity failure is introduced. The new Full details: Cmux Swift ConcurrencyExplanation PASS. The pull-request diff adds no prohibited legacy async pattern. The new Full details: Cmux Swift `@Concurrent`Explanation PASS: The PR diff introduces no Full details: Cmux Swift Package BoundariesExplanation PASS — The pull request keeps the independently testable socket logic behind the existing Full details: Cmux Swiftpm LockfilesExplanation PASS. The PR changes only Swift source and test files. Full details: Cmux Swift LoggingExplanation PASS: The PR adds no Full details: Cmux User-Facing Error PrivacyExplanation PASS — The production diff changes socket recovery and internal Sentry telemetry only. The failure callback sends breadcrumbs and captured errors through Full details: Cmux Full InternationalizationExplanation PASS: The diff adds no user-facing UI, menu, alert, command, web, metadata, or localized app text. The new literals ( Full details: Cmux Swiftui State LayoutExplanation PASS: The pull request does not introduce or materially expand SwiftUI state or layout code. The changed app file, Full details: Cmux Architecture RethinkExplanation PASS. The diff does not introduce an architectural-rethink failure. The socket fallback and errno changes are small local correctness fixes. The new capture gate has one construction and one event-seam owner. Its lock protects a narrow cross-thread telemetry set; it does not add timing, polling, delayed dispatch, or lifecycle repair. The previous TerminalController NSLock and cooldown cache are removed. SocketControlServer remains the authoritative owner of listener lifecycle state, and the existing synchronous listenerDidStart transition resets the gate. No duplicate entrypoint wiring or UI lifecycle ownership changes were introduced. Full details: Cmux Swift Auxiliary Window Close ShortcutsExplanation PASS. The PR changes socket policy, transport error handling, failure capture, and related tests. The diff adds or modifies no user-visible NSWindow, NSPanel, NSWindowController, SwiftUI Window, WindowGroup, close-shortcut handler, or window identifier assignment. The deterministic lint also passes: Full details: Cmux Source ArtifactsExplanation PASS — The PR changes only Swift source, documentation comments, and Swift test files under the expected source and test directories. The complete diff contains no artifact-like paths, binary files, generated logs, caches, build output, or scratch directories. The Full details: Cmux No Test Or Debug Seam In Production SourceExplanation PASS: The production diff adds no test/debug seam. Full details: Cmux No Ambient Global StateExplanation PASS: The diff adds no ambient global state that matches the failure conditions.
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
23866f3 CLI Sentry: per-failure-class fingerprints, mute Not-connected race, throttle timeouts (manaflow-ai#11051) aa865fb iOS: opening a workspace restores its last opened tab (manaflow-ai#11188) 97da40e Escape uncreatable socket state directory to /tmp; dedupe listener-failure captures per episode (manaflow-ai#11050)
…ilure captures per episode (manaflow-ai#11050) * Add failing tests for stable-socket state-directory escape and mkdir errno fidelity Machines whose ~/.local/state/cmux cannot be created (root-owned after a sudo install, or an I/O-erroring home volume) loop forever at stage create_lock_directory: the current fallback routes the stable default to a sibling inside the same uncreatable directory, and applies no fallback at all when path resolution already selected the user-scoped sibling (CMUXTERM-MACOS-2MHE/2FVF/25PE breadcrumbs show wake restarts at cmux-<uid>.sock with zero fallback crumbs). The transport also collapses Cocoa-domain mkdir errors to EIO, hiding the real errno in telemetry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Escape uncreatable socket state directory to /tmp and dedupe listener-failure captures per episode A machine whose ~/.local/state/cmux cannot be created (root-owned after a sudo install, or an I/O-erroring home volume) never got a working socket listener: the bind fallback moved the shared stable path to the user-scoped sibling inside the same uncreatable directory, and applied no fallback at all when resolution had already picked the user-scoped path. Every wake/activation restart re-failed at create_lock_directory and re-captured to Sentry after each 60s cooldown window (~1400 events/day per wedged machine). Now both stable paths escape create_directory/create_lock_directory failures to the legacy /tmp per-user path, which the CLI already discovers, so the listener starts and the wake loop ends. mkdir failures surface the underlying POSIX errno instead of collapsing Cocoa-domain errors to EIO. Listener-failure captures are deduped by a stateful gate: once per (message|stage|path|errno) key per failure episode, reset when the listener starts successfully, and path.missing on debug-like bundle ids stays breadcrumb-only because dev cleanup scripts delete /tmp dev sockets and the path monitor self-heals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Fixes the live
socket.listener.start.failedloop. Prior-bad: a machine whose~/.local/state/cmuxcannot be created (root-owned after a pastsudoinstall, or an I/O-erroring home volume) never got a listener. The bind fallback moved the shared stable path to the user-scoped sibling inside the same uncreatable directory, and applied no fallback at all when path resolution had already selected the user-scoped path (the wedged machines' breadcrumbs show wake restarts atcmux-<uid>.sockwith zero fallback crumbs). Everyworkspace.didWakerestart re-failed at stagecreate_lock_directoryand re-captured after each 60s cooldown window, ~1400 events/day per machine forever.Now:
SocketListenerPolicy.fallbackSocketPathAfterBindFailureaccepts both stable paths as the requested path and routescreate_directory/create_lock_directoryfailures to the legacy/tmp/cmux-<uid>.sock, whichCLISocketPathResolveralready lists as an implicit candidate, so the listener starts and the wake loop ends.ensureSocketParentDirectoryExistsunwraps theNSUnderlyingErrorKeychain to report the real POSIX errno instead of collapsing Cocoa-domain mkdir errors to EIO (the events showed a misleading "errno 5"). Listener-failure capture dedup moves from a 60s per-key cooldown to a statefulSocketListenerFailureCaptureGate: one capture per(message|stage|path|errno)key per failure episode, reset on successful listener start, andsocket.listener.path.missingstays breadcrumb-only on debug-like bundle ids because dev cleanup scripts routinely delete/tmpdev sockets and the path monitor self-heals.Commit 1 adds the failing policy and errno tests (CI red), commit 2 the fix (green). Supersedes the policy half of #9228 (same
/tmpescape for the stable default) and extends it to the user-scoped path that PR left uncovered.Sentry issues addressed:
Principled: the fallback targets the one path family the failing mechanism cannot poison, telemetry reports true errnos, and rate limiting is a single stateful reporter keyed to listener lifecycle rather than a timer. Residual risk: a machine where
/tmpis also unusable still fails, now captured once per session instead of continuously.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Fixes the infinite
socket.listener.start.failedloop on machines whose socket state directory (~/.local/state/cmux) can't be created (root-owned after a pastsudoinstall, or an I/O-erroring home volume): both stable paths now fall back to the legacy/tmp/cmux-<uid>.sock, so the listener starts and the wake loop ends. Listener-failure captures are now deduped per failure episode instead of on a 60-second cooldown, cutting ~1,400 events/day per wedged machine down to one per distinct failure.Bug Fixes
fallbackSocketPathAfterBindFailurenow also accepts the user-scoped stable path and routescreate_directory/create_lock_directoryfailures to the legacy/tmpper-user path, whichCLISocketPathResolveralready lists as a candidate.ensureSocketParentDirectoryExistsunwrapsNSUnderlyingErrorKeychains so telemetry reports the real POSIX errno instead of collapsing Cocoa-domain mkdir errors to EIO.SocketListenerFailureCaptureGatecaptures once per(message|stage|path|errno)key per episode, resets on successful listener start, and keepssocket.listener.path.missingbreadcrumb-only on debug-like bundle ids since dev cleanup deletes/tmpdev sockets and the path monitor self-heals./tmpis also unusable still fails, now captured once per session instead of continuously.Written for commit e33c834. Summary will update on new commits.
Summary by CodeRabbit
New Features
Bug Fixes