diff --git a/js/worker-threads/src/index.test.ts b/js/worker-threads/src/index.test.ts index 8a3026aa0..76f70317b 100644 --- a/js/worker-threads/src/index.test.ts +++ b/js/worker-threads/src/index.test.ts @@ -781,10 +781,13 @@ describe("WorkerThreads", () => { } ); - it("retries a task once when its reused thread dies before starting it", async () => { + it("retries a task once when its reused thread dies before starting it", async ({ + onTestFinished, + }) => { const executor = new WorkerThreads({ maxThreads: 1 }); + onTestFinished(() => executor.close()); const exiting = executor.handler(testJob, { - exportName: "blockThenExit", + exportName: "exitBeforeNextTask", module: handlers, }); const complete = executor.handler(testJob, { @@ -805,7 +808,6 @@ describe("WorkerThreads", () => { crashedThreads: 1, totalThreads: 1, }); - await executor.close(); }); it("fails an attempt that exceeds its thread's heap limit", async () => { diff --git a/js/worker-threads/src/testdata/handlers.ts b/js/worker-threads/src/testdata/handlers.ts index 360191491..c69f81e2d 100644 --- a/js/worker-threads/src/testdata/handlers.ts +++ b/js/worker-threads/src/testdata/handlers.ts @@ -5,6 +5,8 @@ * the TypeScript source, so every test also exercises the thread's fallback * from a missing `.js` module to its `.ts` source. */ +import { parentPort } from "node:worker_threads"; + import { complete as completeOutcome, snooze as snoozeOutcome, @@ -22,19 +24,6 @@ export const allocateForever: TestHandler = ({ logger }) => { for (;;) retained.push(new Array(100_000).fill(retained.length)); }; -export const blockThenExit: TestHandler = () => { - // Keep the thread busy after returning so the next run message is queued - // behind this callback, then exit before the thread can acknowledge it. - setImmediate(() => { - const end = Date.now() + 100; - while (Date.now() < end) { - // Deliberately block this isolated thread. - } - process.exit(9); - }); - return completeOutcome(); -}; - export const complete: TestHandler = ({ job }) => completeOutcome({ output: { value: job.args.value ?? null } }); @@ -93,6 +82,14 @@ export const echoExact: TestHandler = ({ return completeOutcome({ output: { id } }); }; +export const exitBeforeNextTask: TestHandler = () => { + // Replace the run listener so the next task kills this thread before it + // can acknowledge the task. A setImmediate callback races with that message. + parentPort?.removeAllListeners("message"); + parentPort?.once("message", () => process.exit(9)); + return completeOutcome(); +}; + export const exitWhenIdle: TestHandler = () => { setImmediate(() => process.exit(7)); return completeOutcome();