fix(memory): Fix timeout, interval, and subscription cleanup
Summary
Fix various small memory leaks from uncleaned timeouts, intervals, and event subscriptions across the codebase.
Fixes #9156
Problems
1. WebFetch Timeout (webfetch.ts)
When fetch throws an error, the timeout is not cleared.
2. Models setInterval (models.ts)
A setInterval is created but never cleared, even when the module is unloaded.
3. Bus.subscribe Return Value (github.ts)
The unsubscribe function returned by Bus.subscribe() is not captured or called.
Solution
WebFetch - Use try/finally
const timeout = setTimeout(...)
try {
const response = await fetch(...)
return response
} finally {
clearTimeout(timeout)
}
Models - Track interval for cleanup
const intervalId = setInterval(...)
process.on("exit", () => clearInterval(intervalId))
Bus.subscribe - Capture unsubscribe
Store the unsubscribe function for later cleanup.
Changes
-
packages/opencode/src/util/webfetch.ts- Clear timeout in finally block -
packages/opencode/src/provider/models.ts- Add interval cleanup on exit -
packages/opencode/src/github/github.ts- Capture Bus.subscribe return value
Testing
- [x] TypeScript compilation passes (
bun turbo typecheck) - [x] Unit tests pass (725 tests, 0 failures)
Note: Manual testing of timeout/interval cleanup requires runtime verification which was not performed.
Thanks for your contribution!
This PR doesn't have a linked issue. All PRs must reference an existing issue.
Please:
- Open an issue describing the bug/feature (if one doesn't exist)
- Add
Fixes #<number>orCloses #<number>to this PR description
See CONTRIBUTING.md for details.
The following comment was made by an LLM, it may be inaccurate:
Potential Related PRs Found:
-
#9147 - "fix(memory): Fix event listener leaks in TUI and Slack bot"
- Related memory cleanup fix, likely part of same cleanup initiative
-
#9146 - "fix(acp): Fix memory leak in session event streams"
- Related memory leak fix in event streams
-
#9145 - "fix(mcp): Fix memory leaks in OAuth transport and process cleanup"
- Related memory leak fixes across the codebase
-
#7914 - "fix(core): add dispose functions to prevent subscription memory leaks"
- Addresses subscription cleanup similar to PR #9148's Bus.subscribe fix
-
#7032 - "fix(core): add dispose functions to prevent subscription memory leaks"
- Previous attempt at addressing subscription memory leaks
-
#5350 - "Add timeout for file watcher subscribe to address hangs on Rosetta x86 emulation"
- Related to timeout handling
These appear to be part of a broader memory leak cleanup effort (related to issue #5363 mentioned in the PR). PRs #9145, #9146, and #9147 are particularly close in scope and timing, suggesting they may be related fixes across different modules. Consider checking if any of these address the same files or can be consolidated.