mu-ad5x serve: abort the presence task on shutdown — mu serve hung after stdin close#490
Merged
Merged
Conversation
…ter stdin close The etcd-lease presence task (lyksmpsp) is an infinite reconcile loop holding a Sessions clone, spawned with its JoinHandle dropped. mu's shutdown is reference-driven — serve's exit waits on session channels closing — so on any box where etcd is reachable the task kept every session alive forever and `mu serve` never exited after stdin closed (observed: just smoke killed at its 5s guard on a clean change atop lyksmpsp; clean exit one commit earlier). Apply the file's own established pattern for exactly this hazard (the MCP listener's AbortOnDrop): presence::spawn now returns its JoinHandle (#[must_use]), and serve wraps it in AbortOnDrop captured by the transport closure — dropping the handler aborts the task and releases its Sessions clone, letting the documented shutdown cascade complete. Aborting is crash-equivalent and safe by the lease design: the etcd lease expires at TTL and the peer keys vanish with it — the same cleanup a daemon crash gets. Verified on this box (etcd reachable, presence active): just smoke now completes AND mu serve exits cleanly (previously killed at the 5s guard); lease-registered still logged, ask unaffected.
sahuagin
approved these changes
Jul 14, 2026
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.
Fixes mu-ad5x: since the etcd-lease presence merge (
949fed77),mu servenever exits after stdin closes on any box where etcd is reachable — including the serve child undermu solo. Repro:just smokecompletes the ask, logsdialogue presence: lease-registered, then hangs until the recipe's 5s guard kills it; one commit earlier it exits cleanly.Root cause
presence::spawnstarts an infinite reconcile loop (lease keepalive/re-grant + peer-key reconcile everyttl/3) holding aSessionsclone, and drops theJoinHandle. mu's shutdown is reference-driven — serve's exit waits on session channels closing — so the immortal clone wedges the documented shutdown cascade.serve/mod.rsalready names this exact hazard and solves it for the MCP listener ("transport::serve's shutdown cascade … deadlocks if any external clone keeps those alive. AbortOnDrop is captured by the handler closure…"); the presence task was the one spawn without the guard.Change
presence::spawnreturns itsJoinHandle, marked#[must_use = "tie this handle to shutdown (AbortOnDrop) or serve never exits (mu-ad5x)"]so the omission can't silently recur.AbortOnDropcaptured by the transport closure, exactly likemcp_guard: dropping the handler aborts the task and releases itsSessionsclone, letting the cascade complete.Aborting is crash-equivalent and safe by the lease design: the etcd lease expires at TTL and the peer keys vanish with it — the same cleanup a daemon crash gets. No graceful revoke needed.
Verification
On this box (etcd reachable, presence active):
just smokenow logslease-registered, answers, and exits cleanly (exit 0) where it previously hung to the kill guard. Fulljust ci-aiprgreen.Gate
pre-pr-check green; consensus panel PASS — unanimous approve in 1 round, all four (focused) seats live.
🤖 Generated with Claude Code
https://claude.ai/code/session_01REB3QZvP3arA2cLMVRgYam