Skip to content

fix(tray): launch over a dead core's socket without the 60s wait - #1815

Merged
Dumbris merged 2 commits into
smart-mcp-proxy:mainfrom
poolski:fix/tray-stale-socket-launch
Nov 2, 2026
Merged

Dumbris merged 2 commits into
smart-mcp-proxy:mainfrom
poolski:fix/tray-stale-socket-launch

Conversation

@poolski

@poolski poolski commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Description

When a core exits without cleaning up (crash, SIGKILL, the app being replaced while it runs), it leaves ~/.mcpproxy/mcpproxy.sock behind. On the next start the tray probes that socket, gets a refusal, and treats it as a core that may be there: it waits out unresponsiveCoreTimeout (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 holds config.db, it launches immediately through the existing spawn path (confirmNothingIsListening, then launchWithRetries). The tray still never unlinks the socket; the core's cleanupStaleSocket removes it.

The 60 s wait stays for every other case:

Testing

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.
@poolski
poolski marked this pull request as ready for review November 2, 2026 11:44
…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>
@Dumbris
Dumbris enabled auto-merge (squash) November 2, 2026 17:45
@Dumbris

Dumbris commented Nov 2, 2026

Copy link
Copy Markdown
Member

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 /tmp now use a private directory (the derived lock path was /tmp/config.db, so a stray unheld file there would have made the shortcut fire), a maySpawn: false case for the new condition, and two doc comments updated for the new path. Full swift test is 1755/0. Auto-merge is armed.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Dumbris
Dumbris merged commit 866adef into smart-mcp-proxy:main Nov 2, 2026
44 of 46 checks passed
@Dumbris

Dumbris commented Nov 2, 2026

Copy link
Copy Markdown
Member

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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants