Repository navigation
fix(tray): launch over a dead core's socket without the 60s wait - #1815
Conversation
When a core exits without cleaning up, it leaves mcpproxy.sock behind. On the next start the tray probed that socket, got a refusal, and waited out unresponsiveCoreTimeout (60s) before checking the data directory lock and launching a core. start() now checks the lock first. If the socket has refused every probe and nobody holds config.db, it launches immediately through the existing path. bbolt takes the lock before a core binds its listener, so a live core, even a saturated one (GH smart-mcp-proxy#933), still gets the full wait. An unknown lock state, such as a socket with no database beside it, also keeps the wait.
…er maySpawn=false shortcut The startup shortcut derives the data-directory lock from the socket's directory, so CoreLivenessTests that leave a refusing stub at the default /tmp path would consult a stray /tmp/config.db. Give the two such tests a private scratch directory. Add a SaturatedCoreEscalationTests case pinning that start(maySpawn: false) never launches beside a free lock, and update two doc comments to match the new flow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks — the lock-first shortcut is exactly right and keeps the #933 guarantees. Review found only test hygiene, which I pushed on top: the two CoreLivenessTests that leave a refusing socket in bare |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Merged. Thank you, @poolski! Every tray start after a crash or SIGKILL used to sit a full minute on the dead core's socket; checking the data-directory lock up front turns that into an immediate launch while keeping the saturated-core guarantee from #933 intact. Contributions like this are what keep MCPProxy moving, and they matter a lot to the project. One small ask, only if you feel like it: a short public note about your change (a tweet, a LinkedIn post, a line in a community you are part of) helps more people discover MCPProxy. No pressure at all, and I would be glad to repost it. |
Description
When a core exits without cleaning up (crash, SIGKILL, the app being replaced while it runs), it leaves
~/.mcpproxy/mcpproxy.sockbehind. On the next start the tray probes that socket, gets a refusal, and treats it as a core that may be there: it waits outunresponsiveCoreTimeout(60 s) and only then checks the data directory lock (DataDirectoryLock.probe), finds it free, and launches a core. Every start after an unclean exit takes a minute before the core comes up.start()now checks the lock up front. If every probe has refused (socketEvidence.onlyEverRefused) and nobody holdsconfig.db, it launches immediately through the existing spawn path (confirmNothingIsListening, thenlaunchWithRetries). The tray still never unlinks the socket; the core'scleanupStaleSocketremoves it.The 60 s wait stays for every other case:
.unknown, for example a socket with no database beside it;maySpawnfalse).Testing
SaturatedCoreEscalationTests: a refusing socket beside an unheldconfig.dblaunches within 2 s with a 30 s deadline (fails without the change), and a refusing socket with no database still waits. The existing GH tray: a live core with a saturated listen backlog can be launched over, producing doomed spawns and a misleading error #933 cases are unchanged.swift testinnative/macos/MCPProxy