diff --git a/packages/plugins/sandbox-providers/kubernetes/src/pod-exec.ts b/packages/plugins/sandbox-providers/kubernetes/src/pod-exec.ts index 91010d8a..41904008 100644 --- a/packages/plugins/sandbox-providers/kubernetes/src/pod-exec.ts +++ b/packages/plugins/sandbox-providers/kubernetes/src/pod-exec.ts @@ -155,7 +155,15 @@ export async function execInPod( websocketPromise .then((webSocket) => { ws = webSocket as WebSocketLike; - if (!settled && stdinStream && stdinPayload) { + if (settled) { + try { + ws.close(); + } catch { + // Ignore best-effort close failures. + } + return; + } + if (stdinStream && stdinPayload) { stdinStream.end(stdinPayload); } ws.on("close", (code: number, reason: Buffer) => { diff --git a/packages/plugins/sandbox-providers/kubernetes/test/unit/pod-exec.test.ts b/packages/plugins/sandbox-providers/kubernetes/test/unit/pod-exec.test.ts index d3184f64..d9fb3c68 100644 --- a/packages/plugins/sandbox-providers/kubernetes/test/unit/pod-exec.test.ts +++ b/packages/plugins/sandbox-providers/kubernetes/test/unit/pod-exec.test.ts @@ -116,6 +116,7 @@ describe("execInPod", () => { let resolveWebsocket: ((ws: EventEmitter) => void) | undefined; let observedStdin = ""; let observedStdinFinished = false; + const ws = Object.assign(new EventEmitter(), { close: vi.fn() }); execMock.mockImplementation((_namespace, _pod, _container, _command, _stdout, _stderr, stdin) => { stdin?.on("data", (chunk: Buffer) => { @@ -132,9 +133,10 @@ describe("execInPod", () => { const result = await execInPod({} as never, "ns", "pod-1", "agent", ["base64", "-d"], "abc", 5); expect(result.timedOut).toBe(true); - resolveWebsocket?.(new EventEmitter()); + resolveWebsocket?.(ws); await Promise.resolve(); + expect(ws.close).toHaveBeenCalled(); expect(observedStdin).toBe(""); expect(observedStdinFinished).toBe(false); });