fix: resolve lifecycle memory leaks by cleaning up listeners and root closures (#25049)

This commit is contained in:
Spencer
2026-04-10 00:21:14 -04:00
committed by GitHub
parent 43b93e9e1b
commit 5fc8fea8d7
8 changed files with 108 additions and 18 deletions
@@ -208,6 +208,7 @@ describe('ShellExecutionService', () => {
beforeEach(() => {
vi.clearAllMocks();
ExecutionLifecycleService.resetForTest();
ShellExecutionService.resetForTest();
mockSerializeTerminalToObject.mockReturnValue([]);
mockIsBinary.mockReturnValue(false);
mockPlatform.mockReturnValue('linux');
@@ -1247,6 +1248,8 @@ describe('ShellExecutionService child_process fallback', () => {
beforeEach(() => {
vi.clearAllMocks();
ExecutionLifecycleService.resetForTest();
ShellExecutionService.resetForTest();
mockIsBinary.mockReturnValue(false);
mockPlatform.mockReturnValue('linux');
@@ -1662,6 +1665,8 @@ describe('ShellExecutionService execution method selection', () => {
beforeEach(() => {
vi.clearAllMocks();
ExecutionLifecycleService.resetForTest();
ShellExecutionService.resetForTest();
onOutputEventMock = vi.fn();
// Mock for pty
@@ -1786,6 +1791,8 @@ describe('ShellExecutionService environment variables', () => {
beforeEach(() => {
vi.clearAllMocks();
ExecutionLifecycleService.resetForTest();
ShellExecutionService.resetForTest();
vi.resetModules(); // Reset modules to ensure process.env changes are fresh
// Mock for pty
@@ -704,7 +704,10 @@ export class ShellExecutionService {
const finalStrippedOutput = stripAnsi(combinedOutput).trim();
const exitCode = code;
const exitSignal = signal ? os.constants.signals[signal] : null;
const exitSignal =
signal && os.constants.signals
? (os.constants.signals[signal] ?? null)
: null;
const resultPayload: ShellExecutionResult = {
rawOutput: Buffer.from(''),
@@ -1503,4 +1506,16 @@ export class ShellExecutionService {
signal: info.signal,
}));
}
/**
* Resets the internal state of the ShellExecutionService.
* This is intended for use in tests to ensure isolation.
*/
static resetForTest(): void {
this.activePtys.clear();
this.activeChildProcesses.clear();
this.backgroundLogPids.clear();
this.backgroundLogStreams.clear();
this.backgroundProcessHistory.clear();
}
}
+3 -6
View File
@@ -812,7 +812,7 @@ type StatusChangeListener = (
serverName: string,
status: MCPServerStatus,
) => void;
const statusChangeListeners: StatusChangeListener[] = [];
const statusChangeListeners: Set<StatusChangeListener> = new Set();
/**
* Add a listener for MCP server status changes
@@ -820,7 +820,7 @@ const statusChangeListeners: StatusChangeListener[] = [];
export function addMCPStatusChangeListener(
listener: StatusChangeListener,
): void {
statusChangeListeners.push(listener);
statusChangeListeners.add(listener);
}
/**
@@ -829,10 +829,7 @@ export function addMCPStatusChangeListener(
export function removeMCPStatusChangeListener(
listener: StatusChangeListener,
): void {
const index = statusChangeListeners.indexOf(listener);
if (index !== -1) {
statusChangeListeners.splice(index, 1);
}
statusChangeListeners.delete(listener);
}
/**