vitest-dev / vitest-dev/vitest
`startVitest` with `runner: forks` has incorrect SIGTERM fallback on windows; fails to produce profiling logs
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 17.1k
- Forks
- 2k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 94
Description
Describe the bug
Long story short, I made a script to run Vitest with Node.JS profiling logs enabled.
To my surprise, what should be an extremely simple task ended up being platform-dependent - no profiling output would be written when running on Windows machines.
Delving a bit deeper into Vitest source, it appears the SIGTERM workaround for nodejs/node#55094 is the culprit at hand:
Windows does not emit SIGTERM events on a process being killed (mapping to a native TerminateProcess API that kills without running handlers).
This means that --heap-prof and similar flags are effectively platform-dependent and will not work on non-Linux platforms.
[!IMPORTANT]
Switching tothreadsrunner does solve the issue, though having the default runner option be platform-dependent is obviously not very ideal.
Reproduction
import { startVitest } from 'vitest/node';
import { glob } from 'node:fs/promises';
import { basename, join } from 'node:path';
const execArgv = [
'--heap-prof',
`--heap-prof-name=vitest.heapprofile`,
`--heap-prof-dir=./temp`,
];
const vitest = await startVitest('test', undefined, { execArgv });
await vitest.close();
This outputs to ./temp only on UNIX-like systems vs. everything else.
MRE for SIGTERM behavior
import { fork } from "node:child_process";
import { writeFileSync } from "node:fs";
writeFileSync(
"./example.mjs",
`
process.on("SIGTERM", () => {
// only runs on windows
console.log("[child] SIGTERM received, exiting cleanly...");
process.exit(0);
});
console.log("[child] Hello world");
// Keep alive
setInterval(() => {}, 1_000);
`,
"utf8",
);
console.log(`Platform: ${process.platform}`);
console.log("[parent] Forking child...\n");
const child = fork("./example.mjs", { stdio: "inherit" });
// Give the child a moment to set up its SIGTERM handler
setTimeout(() => {
console.log("\n[parent] Sending kill() to child (pid %d)...", child.pid);
child.kill(); // sends SIGTERM on Linux; calls TerminateProcess on Windows
child.on("exit", (code, signal) => {
console.log("[parent] Child exited — code: %s, signal: %s", code, signal);
});
}, 500);
System Info
System:
OS: Windows 11 10.0.26200
CPU: (8) x64 AMD Ryzen 5 7520U with Radeon Graphics
Memory: 2.82 GB / 15.24 GB
Binaries:
Node: 24.14.0 - C:\Users\taylo\AppData\Local\Volta\tools\image\node\24.14.0\node.EXE
npm: 11.9.0 - C:\Users\taylo\AppData\Local\Volta\tools\image\node\24.14.0\npm.CMD
pnpm: 10.28.2 - C:\Program Files\Volta\pnpm.EXE
Browsers:
Chrome: 146.0.7680.80
Edge: Chromium (140.0.3485.54)
Internet Explorer: 11.0.26100.7309
npmPackages:
@vitest/coverage-v8: ^4.0.18 => 4.0.18
@vitest/expect: ^4.0.18 => 4.0.18
@vitest/utils: ^4.0.18 => 4.0.18
vite: ^7.3.1 => 7.3.1
vitest: ^4.0.18 => 4.0.18
vitest-canvas-mock: ^1.1.3 => 1.1.3
(The linux one was on stackblitz, also with vitest 4.0.18. I also have reproduced it working on my local WSL installation running Ubuntu, but it really doesn't matter.)
Used Package Manager
pnpm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/vitest/src/runtime/workers/init-forks.ts at the linked SIGTERM workaround, then run the provided startVitest reproduction with runner: forks on Windows and a Unix-like system. Compare the process termination behavior and profiling output; done means the Windows run produces the expected profiling logs without regressing the Unix-like case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100