fix(web): dispose idle MCP server instances to prevent process accumulation#15326
fix(web): dispose idle MCP server instances to prevent process accumulation#15326lytedev wants to merge 1 commit intoanomalyco:devfrom
Conversation
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Based on my search, I found several related PRs that address similar issues with process management and cleanup: Potentially Related PRs:
These PRs appear to be addressing the same class of issues (process accumulation, memory leaks, signal handlers, and graceful shutdown) across different modes of the application. PR #14092 seems most relevant as it specifically targets web/serve shutdown issues. |
11afb64 to
243d613
Compare
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
…lation
In `opencode web` mode, switching projects creates new Instance entries (each
spawning MCP server child processes) that are never cleaned up. Unlike the TUI
which calls shutdown()/disposeAll() on exit, the web command blocks forever
with `await new Promise(() => {})` and never reaches its `server.stop()` call.
This causes unbounded process growth — each project switch leaks ~200MB of MCP
server processes (linear, notion, etc.) that persist for the lifetime of the
web server.
Fix:
- Add signal handlers (SIGINT, SIGTERM, SIGHUP) to the web command that call
Instance.disposeAll() with a 5s timeout before exiting
- Add idle eviction to Instance: track last access time per directory, sweep
every 60s, and dispose instances idle for >5 minutes
- Clean up lastAccess bookkeeping in dispose() and disposeAll()
243d613 to
42f10f1
Compare
Issue for this PR
Closes #14091
Type of change
What does this PR do?
Same root cause as #14092 —
server.stop()is unreachable dead code afterawait new Promise(() => {})inweb.ts, and no signal handlers exist. I also added idle eviction of cached Instance entries, which #14092 doesn't cover: without it, each project switch accumulates MCP server processes (~200MB each) for the entire lifetime of the web server, even if those projects are never revisited.Signal handlers (SIGINT/SIGTERM/SIGHUP) follow the existing
worker.tspattern. Idle eviction sweeps every 60s and disposes instances idle >5 minutes. I didn't touchserve.tsor the SSE cleanup — happy to add those if this gets traction, or #14092 can cover them.How did you verify your code works?
Ran patched and unpatched instances side by side on the same machine. After switching between 8 projects over ~30 minutes:
bun turbo typecheck(16/16 pass),bun turbo test(1172 pass, 0 fail).Screenshots / recordings
No UI changes.
Checklist