From e4f847ff68ba877affb4148d30c9e8c8167ac33c Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 27 Apr 2026 20:33:40 +0200 Subject: [PATCH] fix(coding-agent): close bash executor temp streams closes #3786 --- packages/coding-agent/CHANGELOG.md | 2 ++ .../coding-agent/src/core/bash-executor.ts | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 4596a3de..f6525130 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -4,10 +4,12 @@ ### Added +- Added `warnings.anthropicExtraUsage` and a `/settings` warnings submenu to suppress the Anthropic extra usage billing warning ([#3808](https://github.com/badlogic/pi-mono/issues/3808)) - Added `ctx.ui.setWorkingVisible()` so extensions can hide the built-in interactive working loader row without reserving layout space, plus a border-status editor example that moves working state into a custom editor border ([#3674](https://github.com/badlogic/pi-mono/issues/3674)) ### Fixed +- Fixed bash executor temp output streams leaking file descriptors when output was truncated by line count ([#3786](https://github.com/badlogic/pi-mono/issues/3786)) - Fixed extension `pi.setSessionName()` updates to refresh the interactive terminal title immediately ([#3686](https://github.com/badlogic/pi-mono/issues/3686)) - Fixed `/tree` cancellation via `session_before_tree` leaving the session stuck in compaction state ([#3688](https://github.com/badlogic/pi-mono/issues/3688)) - Fixed Escape interrupt handling when extensions hide the built-in working loader row ([#3674](https://github.com/badlogic/pi-mono/issues/3674)) diff --git a/packages/coding-agent/src/core/bash-executor.ts b/packages/coding-agent/src/core/bash-executor.ts index 3c185e21..ee55611e 100644 --- a/packages/coding-agent/src/core/bash-executor.ts +++ b/packages/coding-agent/src/core/bash-executor.ts @@ -110,15 +110,14 @@ export async function executeBashWithOperations( signal: options?.signal, }); - if (tempFileStream) { - tempFileStream.end(); - } - const fullOutput = outputChunks.join(""); const truncationResult = truncateTail(fullOutput); if (truncationResult.truncated) { ensureTempFile(); } + if (tempFileStream) { + tempFileStream.end(); + } const cancelled = options?.signal?.aborted ?? false; return { @@ -129,10 +128,6 @@ export async function executeBashWithOperations( fullOutputPath: tempFilePath, }; } catch (err) { - if (tempFileStream) { - tempFileStream.end(); - } - // Check if it was an abort if (options?.signal?.aborted) { const fullOutput = outputChunks.join(""); @@ -140,6 +135,9 @@ export async function executeBashWithOperations( if (truncationResult.truncated) { ensureTempFile(); } + if (tempFileStream) { + tempFileStream.end(); + } return { output: truncationResult.truncated ? truncationResult.content : fullOutput, exitCode: undefined, @@ -149,6 +147,10 @@ export async function executeBashWithOperations( }; } + if (tempFileStream) { + tempFileStream.end(); + } + throw err; } }