diff --git a/tests/index.js b/tests/index.js index 95a24d2c..8a395461 100644 --- a/tests/index.js +++ b/tests/index.js @@ -12,6 +12,11 @@ const assert = require("node:assert"); const TEST_TIMEOUT = 60000; +// see tests/win-exit-delay.cjs: without it every test crashes on exit under Node 24+ on Windows +const NODE_ARGS = process.platform === 'win32' + ? `--require "${path.join(__dirname, 'win-exit-delay.cjs')}" ` + : ''; + const testPath = path.join(__dirname, 'tests'); let testCategories = fs.readdirSync(testPath).sort((a, b) => parseInt(a) - parseInt(b)); @@ -65,7 +70,7 @@ for (const testCategory of testCategories) { }; let execTest = async (testPath) => { - return (await exec(`node ${testPath}`, {maxBuffer: 1024 * 1024 * 100})).stdout + return (await exec(`node ${NODE_ARGS}${testPath}`, {maxBuffer: 1024 * 1024 * 100})).stdout } try { diff --git a/tests/win-exit-delay.cjs b/tests/win-exit-delay.cjs new file mode 100644 index 00000000..e90260b8 --- /dev/null +++ b/tests/win-exit-delay.cjs @@ -0,0 +1,19 @@ +// Node 24 and later crash on Windows when process.exit() runs while undici still has +// keep-alive sockets open: "Assertion failed: !(handle->flags & UV_HANDLE_CLOSING), +// file src\win\async.c" (nodejs/node#56645). Every test here ends with process.exit() +// right after fetching, so they hit it, and the crash also loses whatever stdout was +// still buffered, which makes the captured output unreliable on top of the exit code. +// +// Letting the loop settle first avoids it. Preloaded by tests/index.js on win32 only, +// so nothing changes on Linux or macOS. + +const EXIT_DELAY_MS = 100; + +const realExit = process.exit.bind(process); + +process.exit = (code) => { + if (code !== undefined) { + process.exitCode = code; + } + setTimeout(() => realExit(process.exitCode), EXIT_DELAY_MS); +};