fix(lsp): cleanup orphaned LSP servers on session.deleted (#676)
* fix(lsp): cleanup orphaned LSP servers on session.deleted When parallel background agent tasks complete, their LSP servers (for repos cloned to /tmp/) remain running until a 5-minute idle timeout. This causes memory accumulation with heavy parallel Sisyphus usage, potentially leading to OOM crashes. This change adds cleanupTempDirectoryClients() to LSPServerManager (matching the pattern used by SkillMcpManager.disconnectSession()) and calls it on session.deleted events. The cleanup targets idle LSP clients (refCount=0) for temporary directories (/tmp/, /var/folders/) where agent tasks clone repos. * chore: retrigger CI checks
This commit is contained in:
@@ -63,6 +63,7 @@ import {
|
||||
createSisyphusTask,
|
||||
interactive_bash,
|
||||
startTmuxCheck,
|
||||
lspManager,
|
||||
} from "./tools";
|
||||
import { BackgroundManager } from "./features/background-agent";
|
||||
import { SkillMcpManager } from "./features/skill-mcp-manager";
|
||||
@@ -427,6 +428,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||
}
|
||||
if (sessionInfo?.id) {
|
||||
await skillMcpManager.disconnectSession(sessionInfo.id);
|
||||
await lspManager.cleanupTempDirectoryClients();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,11 @@ import {
|
||||
lsp_rename,
|
||||
lsp_code_actions,
|
||||
lsp_code_action_resolve,
|
||||
lspManager,
|
||||
} from "./lsp"
|
||||
|
||||
export { lspManager }
|
||||
|
||||
import {
|
||||
ast_grep_search,
|
||||
ast_grep_replace,
|
||||
|
||||
@@ -182,6 +182,26 @@ class LSPServerManager {
|
||||
this.cleanupInterval = null
|
||||
}
|
||||
}
|
||||
|
||||
async cleanupTempDirectoryClients(): Promise<void> {
|
||||
const keysToRemove: string[] = []
|
||||
for (const [key, managed] of this.clients.entries()) {
|
||||
const isTempDir = key.startsWith("/tmp/") || key.startsWith("/var/folders/")
|
||||
const isIdle = managed.refCount === 0
|
||||
if (isTempDir && isIdle) {
|
||||
keysToRemove.push(key)
|
||||
}
|
||||
}
|
||||
for (const key of keysToRemove) {
|
||||
const managed = this.clients.get(key)
|
||||
if (managed) {
|
||||
this.clients.delete(key)
|
||||
try {
|
||||
await managed.client.stop()
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const lspManager = LSPServerManager.getInstance()
|
||||
|
||||
Reference in New Issue
Block a user