You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Memory leak: serve and web commands leak child processes on exit; SSE heartbeat interval leaks on server-initiated close #14091
The serve and web commands have no graceful shutdown. When the process receives SIGTERM or SIGINT, child resources (MCP subprocesses, LSP servers, file watchers, SQLite connections) are never cleaned up because Instance.disposeAll() is never called.
Separately, the SSE /event endpoint leaks a setInterval heartbeat and a Bus.subscribeAll subscription when the server closes a stream (on InstanceDisposed), because cleanup only runs in onAbort — which Hono only fires on client disconnect, not on stream.close().
Bug 1: Dead server.stop() in serve.ts and web.ts
serve.ts:17-18:
awaitnewPromise(()=>{})// blocks forever — never resolvesawaitserver.stop()// unreachable
Same pattern in web.ts:78-79. No signal handlers are registered, so SIGTERM/SIGINT use the kernel default (immediate kill, no cleanup).
The correct pattern already exists in worker.ts:137-147:
Bug 2: SSE heartbeat interval leaks on server-initiated stream close
server.ts:513-539 — clearInterval(heartbeat) and unsub() are inside stream.onAbort(). Hono's onAbort only fires on client disconnect (via ReadableStream.cancel()). When the server closes the stream on InstanceDisposed via stream.close(), the onAbort callback never fires.
Each server-closed SSE client leaks:
One setInterval (10s heartbeat) writing to a closed stream
One Bus.subscribeAll subscription processing every bus event
Steps to reproduce
Bug 1:
bun dev serve --port 14096 &
SERVE_PID=$!
sleep 3
kill -TERM $SERVE_PID
wait $SERVE_PID
echo "exit code: $?"
Exit code is 143 (SIGTERM default), zero shutdown logs, child processes survive. Each orphaned process holds ~200-280MB RSS and they accumulate on every restart.
Bug 2:
Connect an SSE client, trigger InstanceDisposed — heartbeat interval keeps firing after stream.close().
OpenCode version
Current dev branch
Operating System
Linux (also affects macOS — any platform running serve or web)
This issue identifies important root causes for some of the memory leak symptoms reported in existing issues. While there are related reports of orphaned processes, this issue provides:
Specific root causes with exact file locations and code examples
Two distinct bugs (graceful shutdown in serve/web + SSE heartbeat leak)
Activity
github-actions commentedon Feb 18, 2026
This issue identifies important root causes for some of the memory leak symptoms reported in existing issues. While there are related reports of orphaned processes, this issue provides:
Related issues that may benefit from fixes here:
This appears to be the most detailed analysis of the shutdown problem in the codebase.
s2bomb commentedon Feb 18, 2026
Hey @thdxr, thanks for making opencode btw, I love it.
s2bomb commentedon Feb 18, 2026
PR with fix: #14092
This also addresses the orphaned process symptoms reported in #13796 and #12767 for the
serveandwebcode paths.thdxr commentedon Apr 2, 2026
Closing in favor of #20695 where we're collecting all memory-related problems. Please follow that issue for updates.