From e1e59bf0cd18f6434d9396c61adba2a21f51e81f Mon Sep 17 00:00:00 2001 From: Olcan Date: Mon, 19 May 2025 13:16:11 -0700 Subject: [PATCH] fix SIGPIPE and race condition causing dropping of final output ( "command not found" error) on cloudtops (#429) --- packages/server/src/tools/shell.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/server/src/tools/shell.ts b/packages/server/src/tools/shell.ts index 8a1baa2a..73f54b44 100644 --- a/packages/server/src/tools/shell.ts +++ b/packages/server/src/tools/shell.ts @@ -141,7 +141,7 @@ export class ShellTool extends BaseTool { let command = params.command.trim(); if (!command.endsWith('&')) command += ';'; // note the final echo is only to trigger the stderr handler below - command = `{ ${command} }; pgrep -g 0 >${tempFilePath} 2>&1; echo >&2`; + command = `{ ${command} }; pgrep -g 0 >${tempFilePath} 2>&1; ( trap '' PIPE ; echo >&2 )`; // spawn command in specified directory (or project root if not specified) const shell = spawn('bash', ['-c', command], { @@ -160,16 +160,19 @@ export class ShellTool extends BaseTool { let stderr = ''; shell.stderr.on('data', (data: Buffer) => { - // if the temporary file exists, close the streams and ignore any remaining output - // otherwise the streams can remain connected to background processes + let str = data.toString(); + // if the temporary file exists, close the streams and finalize stdout/stderr + // otherwise these streams can delay termination ('close' event) until all background processes exit if (fs.existsSync(tempFilePath)) { shell.stdout.destroy(); shell.stderr.destroy(); - } else { - const str = data.toString(); - stderr += str; - output += str; + // exclude final \n, which should be from echo >&2 unless there are background processes writing to stderr + if (str.endsWith('\n')) { + str = str.slice(0, -1); + } } + stderr += str; + output += str; }); let error: Error | null = null;