Q59: a signal-killed command is reported as failed, not exit code 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-08 10:20:54 -04:00
1 parent a3aee1940a
commit 8775c34650
2 files changed
+19 -4

No files matched your search

+9 -3
View File
@@ -75,12 +75,18 @@ export function runCommand(workspaceRoot: string, command: string, options: { ti
child.stdout.on("data", collect);
child.stderr.on("data", collect);
child.on("error", (error) => finish(`ERROR: ${error.message}`));
child.on("close", (code) => {
finish(`exit code ${code ?? 0}\n${output.text().trim() || "(no output)"}`);
});
child.on("close", (code, signal) => finish(formatCommandResult(code, signal, output.text())));
});
}
/** The tool result for a finished command; no exit code means it was killed, which is never success. */
export function formatCommandResult(code: number | null, signal: NodeJS.Signals | null, text: string): string {
const body = text.trim() || "(no output)";
if (code !== null) return `exit code ${code}\n${body}`;
const how = signal ? `was killed by ${signal} before it exited` : "ended without an exit code";
return `ERROR: the command ${how}; treat it as failed.\n${body}`;
}
/** Kills a process and every process it started; returns why that failed, or null. */
function killProcessTree(pid: number | undefined): string | null {
if (pid === undefined) return null;
+10 -1
View File
@@ -2,7 +2,7 @@ import { mkdtempSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, test, vi } from "vitest";
import { BoundedOutput, runCommand } from "../../src/main/services/workspace-command";
import { BoundedOutput, formatCommandResult, runCommand } from "../../src/main/services/workspace-command";
import { stopRun, withRunControl } from "../../src/main/services/run-control";
describe("bounded command output", () => {
@@ -66,3 +66,12 @@ describe("run_command and run stops", () => {
warn.mockRestore();
});
});
describe("command results", () => {
test("a signal-terminated command is reported as killed, never as exit code 0", () => {
expect(formatCommandResult(0, null, "built")).toBe("exit code 0\nbuilt");
expect(formatCommandResult(2, null, "")).toBe("exit code 2\n(no output)");
expect(formatCommandResult(null, "SIGKILL", "partial")).toBe("ERROR: the command was killed by SIGKILL before it exited; treat it as failed.\npartial");
expect(formatCommandResult(null, null, "")).toBe("ERROR: the command ended without an exit code; treat it as failed.\n(no output)");
});
});