Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Test I ran
node worker_threads.ts
slice run worker_threads.tsworker_threads.ts
import { Worker } from "node:worker_threads";
const show = async (k: string, f: () => unknown) => { let v; try { v = await Promise.race([Promise.resolve().then(f), new Promise((r) => setTimeout(() => r("NEVER SETTLED (2000 ms)"), 2000))]); } catch (e: any) { v = "THROWS " + e.name + ": " + String(e.message).slice(0, 100); } console.log(k.padEnd(52) + JSON.stringify(v)); };
(async () => {
await show("worker: process.exit(3) -> 'exit' code", () => new Promise((res) => { const w = new Worker(`process.exit(3)`, { eval: true }); w.on("exit", (c) => res("exit " + c)); w.on("error", (e: any) => res("error event: " + String(e.message).slice(0, 60))); }));
await show("worker: normal completion -> 'exit' code", () => new Promise((res) => { const w = new Worker(`1+1`, { eval: true }); w.on("exit", (c) => res("exit " + c)); w.on("error", (e: any) => res("error event: " + e.message)); }));
await show("worker: Date survives postMessage", () => new Promise((res, rej) => { const w = new Worker(`const { parentPort } = require("node:worker_threads"); parentPort.on("message", (m) => parentPort.postMessage([m.d instanceof Date, Object.prototype.toString.call(m.d), typeof m.d]));`, { eval: true }); w.on("message", (m) => { Promise.resolve(w.terminate()).then(() => res(m)); }); w.on("error", rej); w.postMessage({ d: new Date(0) }); }));
await show("worker -> parent: Date survives", () => new Promise((res, rej) => { const w = new Worker(`require("node:worker_threads").parentPort.postMessage({ d: new Date(0), e: new Error("x"), r: /a/g })`, { eval: true }); w.on("message", (m) => { Promise.resolve(w.terminate()).then(() => res([m.d instanceof Date, m.e instanceof Error, m.r instanceof RegExp])); }); w.on("error", rej); }));
})();Result
Node v24.22.2:
worker: process.exit(3) -> 'exit' code "exit 3"
worker: normal completion -> 'exit' code "exit 0"
worker: Date survives postMessage [true,"[object Date]","object"]
worker -> parent: Date survives [true,true,true]
Slice v0.10.7:
worker: process.exit(3) -> 'exit' code "error event: Uncaught Error: process.exit(3)\n at <main> (unknown at :1"
worker: normal completion -> 'exit' code "exit 0"
worker: Date survives postMessage [false,"[object String]","string"]
worker -> parent: Date survives [false,true,true]
What is wrong
process.exit(3)inside a worker makes the parent receive an'error'event (Uncaught Error: process.exit(3)) instead of'exit'with code 3. This is the same mechanism as the top-levelprocess.exitbehaviour reported separately, seen from the worker side.- A
Dateposted in either direction is received as a string (typeofis"string"), som.d.getTime()throws in the receiver.Map,Uint8Array,BigInt,ErrorandRegExpsurvive the same round trip, andstructuredClone()in a single isolate preservesDate, so only the worker serialisation path is affected.
Worker start-up, workerData, message round trips, MessageChannel and receiveMessageOnPort matched Node in the same run.
Environment
- Slice
v0.10.7, commitea7c70c, built withcargo +1.96.0 build --release --locked --bin slice - Reference: Node.js
v24.22.2(same script, same machine) - Ubuntu 26.04, Linux 7.0, x86_64
- Item 1 is identical on the
v0.10.5tag.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
siktec-lab commentedon Nov 11, 2026
Fixed in PR #65 (
v0.10.9):Dateinstances (includingInvalid Dateviathis[k] instanceof DatebeforeDate.prototype.toJSONruns) as well asNaNand±InfinityacrossworkerData,postMessage, andMessageChannel.process.exit(code)inside Worker threads directly to the native__slice_process_exit(code)unwind so workers terminate immediately with the exact exit code even whenprocessis referenced (Shard 18 loaded).