fix(cli): normalize exit status on worker cleanup failure (#8049) (#8050)

* fix(cli): normalize exit status on worker cleanup failure (#8049)

* test(cli): verify SDK output status and finalization rejection on exit

* ci: retrigger checks

---------

Co-authored-by: Sarthak Pandey <sarthak@email.com>
This commit is contained in:
NoThingandSarthak Pandey authored and GitHub committed 2026-11-05 18:27:29 +08:00
1 parent 08a923f722
commit fbfb1b768c
2 files changed
+42 -3

No files matched your search

+2 -2
View File
@@ -167,7 +167,7 @@ if (!(await compiledRuntimeExists(runtimeFiles))) {
exit: (code) => {
exiting = true;
void (async () => {
let status = code;
let status = typeof code === "number" ? code : 0;
try {
await closeCliResources();
} catch (cleanup) {
@@ -177,7 +177,7 @@ if (!(await compiledRuntimeExists(runtimeFiles))) {
if (status === 0) status = 1;
}
try {
await resultOutput?.finishSdkOutput(code);
await resultOutput?.finishSdkOutput(status);
} catch (cause) {
if (!stdoutClosed)
process.stderr.write(`${cleanupFailureText(cause)}\n`);
+40 -1
View File
@@ -369,7 +369,7 @@ describe("executable dispatcher JavaScript shutdown", () => {
await installCliRuntime(
workspace,
`export const closeCliResources = () => { globalThis.cleaned = true; ${cleanupFails ? 'return Promise.reject(new Error("worker still owned"));' : ""} }; export const createCli = () => ({ serve: (_args, options) => { options.stdout("pending document"); options.exit(0); } });\n`,
`export const createCliResultOutput = () => ({ handled: false, failed: false, captureSdkOutput: () => true, finishSdkOutput: async () => { if (!globalThis.cleaned) throw new Error("output preceded cleanup"); await new Promise(resolve => setTimeout(resolve, 10)); ${finish} } });\n`,
`export const createCliResultOutput = () => ({ handled: false, failed: false, captureSdkOutput: () => true, finishSdkOutput: async (status) => { if (!globalThis.cleaned) throw new Error("output preceded cleanup"); if (status !== ${cleanupFails ? 1 : 0}) throw new Error("unexpected finish status: " + status); await new Promise(resolve => setTimeout(resolve, 10)); ${finish} } });\n`,
);
const result = await processes.run(
process.execPath,
@@ -383,6 +383,7 @@ describe("executable dispatcher JavaScript shutdown", () => {
scenario === "success" || cleanupFails ? "complete document\n" : "",
);
expect(result.stderr).not.toContain("output preceded cleanup");
expect(result.stderr).not.toContain("unexpected finish status");
if (cleanupFails) expect(result.stderr).toContain("worker still owned");
if (scenario === "write-failure")
expect(result.stderr).toContain("final write failed");
@@ -407,6 +408,44 @@ describe("executable dispatcher JavaScript shutdown", () => {
},
);
workspaceCliTest(
"reports a failed JavaScript worker shutdown when exit is called without a code and passes failure status to SDK output",
async ({ processes, workspace }) => {
await installCliRuntime(
workspace,
'export const closeCliResources = () => Promise.reject(new Error("worker still owned")); export const createCli = () => ({ serve: (_args, options) => { options.exit(); } });\n',
'export const createCliResultOutput = () => ({ handled: false, failed: false, captureSdkOutput: () => false, finishSdkOutput: async (status) => { if (status !== 1) throw new Error("unexpected finish status: " + status); } });\n',
);
const result = await processes.run(
process.execPath,
[workspace.path("scripts/rea.mjs"), "fixture"],
{ cwd: workspace.root },
);
expect(result.exitCode).toBe(1);
expect(result.stderr).toContain("worker still owned");
expect(result.stderr).not.toContain("unexpected finish status");
},
);
workspaceCliTest(
"reports a failed SDK finalization when exit is called without a code",
async ({ processes, workspace }) => {
await installCliRuntime(
workspace,
"export const closeCliResources = () => Promise.resolve(); export const createCli = () => ({ serve: (_args, options) => { options.exit(); } });\n",
'export const createCliResultOutput = () => ({ handled: false, failed: false, captureSdkOutput: () => false, finishSdkOutput: async (status) => { if (status !== 0) throw new Error("unexpected finish status: " + status); throw new Error("SDK finalization failed"); } });\n',
);
const result = await processes.run(
process.execPath,
[workspace.path("scripts/rea.mjs"), "fixture"],
{ cwd: workspace.root },
);
expect(result.exitCode).toBe(1);
expect(result.stderr).toContain("SDK finalization failed");
expect(result.stderr).not.toContain("unexpected finish status");
},
);
workspaceCliTest(
"keeps the closed-pipe status when JavaScript worker shutdown fails",
async ({ processes, workspace }) => {