fix: notice a stopped cmux-tui owner while connected (cx-jniyz.4)
With the app connected to its local cmux-tui owner, an owner that stops answering (SIGSTOP, or wedged in its main loop) went unnoticed. In the cx-jniyz.1 dogfood, no not-connected banner appeared even after 200 s. A stopped process keeps its socket open, so the connection never sees EOF. The only liveness check, the identify heartbeat, ran only for bridged connections.
Change
BridgeHeartbeatbecomesConnectionHeartbeat, with the same behavior:identifyevery interval, and N misses in a row close the transport.DaemonConnectionConfigurationgetsheartbeat(15 s) andheartbeatMisses(2), plus an opt-inlocalHeartbeat(default false). Only the app's main local connection (DaemonService.localConfiguration) turns it on, so page relays and short-lived connections add no idle wakeups. The new heartbeat is listed inplans/cmux-next/idle-wakeups.md.- A stopped owner is now noticed in about 30โ45 s. The connection closes, the store goes
.disconnected, and the existing not-connected banner shows. When the owner answers again, the reconnect loop orRetryWakereconnects.
There are no new visuals; the existing banner now appears when it should. None of the files #20765 touches change.
Verification
- Red first, as a separate commit:
CmuxNextDaemonTests.StoppedOwnerTests(live daemon). It SIGSTOPs the owner by its exact pid, expects.disconnectedwithin 20 s, then SIGCONTs it and expects a reconnect within 30 s.- Red, commit 1a506fa6, fleet job
147f959c12022130358105aa: 346 suites passed; onlyStoppedOwnerTestsfailed. - Green, head
fcbac8b2, joba1d0d0aeacb878da7bb1858a:aStoppedOwnerShowsDisconnectedAndReconnectsWhenItResumes()passed in 4.7 s. The step's exit 1 is the same-tree skip guard on two unrelated acpmux suites. - Between red and green, the test changed only in the field rename (
bridgeHeartbeat*โheartbeat*) and thelocalHeartbeat = trueline, both of which came with the fix.
- Red, commit 1a506fa6, fleet job
- Release compile on
fcbac8b2, job4a7ba555d3a49121483354bc: passed. - Local checks: check-app-size, check-concurrency and crash_ratchet pass, and check-no-godfiles adds nothing new. The conventions lint fails only on the base's
BuiltInAdBlockerSetting.
Not verified in a real app yet. The capture to make: with the App Store open, kill -STOP <owner pid>; the not-connected banner should appear within about 45 s and clear after kill -CONT.
Changelog
Fixed: cmux NEXT shows cmux-tui as not connected when its owner stops responding while connected
๐ค Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes the app keeping cmux-tui shown as connected when its owner stops responding while connected. A stopped or wedged owner keeps its socket open, so the connection never sees EOF; the identify heartbeat only ran for bridged connections. The app's main local connection now runs that heartbeat (every 15 s, 2 unanswered asks close the transport), so a stopped owner shows not connected in about 30โ45 s and reconnects once it answers again.
BridgeHeartbeatis renamedConnectionHeartbeat; the opt-inlocalHeartbeatlimits it to the app's main connection, so page relays and short-lived connections add no idle wakeups.- New
StoppedOwnerTestsSIGSTOPs the owner by pid, expects the store to turn disconnected, then SIGCONTs and expects a reconnect. - The
schemas/defaults/cmux-next.jsonregeneration (addingkey.home.switchView) is a base-branch merge artifact, unrelated to this fix.