Created
April 13, 2026 08:40
-
-
Save izelnakri/5a7f25ab01940f915b01754585ddeac1 to your computer and use it in GitHub Desktop.
Major Node.js BUG: process management/children resources
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ME: Seems like in node.js process/child management is complex and broken api design/intuition-wise, am I correct with this assessment? Seems like we do all these hacks just to patch | |
| what node.js should have done properly under the hood? | |
| ● Partially correct, but the blame is split between Node.js and the OS. Let me be precise about each layer: | |
| Where the complexity is genuinely Node.js's fault: | |
| - detached: true is poorly named and documented. It actually means "create a new process group" — a Unix kernel concept — but the name implies "run independently". Most | |
| developers have no idea it controls the PGID. | |
| - proc.kill() only kills the process you spawned, not its children. Node could have set prctl(PR_SET_PDEATHSIG, SIGKILL) on every spawned child by default (Linux), which would | |
| auto-kill children when the parent dies. It doesn't. | |
| - There's no proc.killTree() or equivalent. You have to know the -pgid trick yourself. | |
| - child.unref() is a Node event-loop concept leaking into process management semantics — it feels like it "detaches" the child, but it only affects whether Node's event loop | |
| waits. | |
| Where the complexity comes from the OS, not Node.js: | |
| - Unix process groups, sessions, and signals predate Node.js by 40 years. The negative-PID trick is a POSIX kernel interface. | |
| - Chrome's multi-process architecture (renderer, GPU, zygote, utility) is Chrome's design for security isolation — any runtime would have the same orphan problem. | |
| - Windows Job Objects vs Unix process groups is a fundamental platform divergence no abstraction fully hides. | |
| The honest comparison: | |
| Python's subprocess, Go's os/exec, and Rust's std::process all have the same problem. You'd write equivalent pgid kill logic in all of them. The difference is that Node.js | |
| targets a broader developer audience that expects more batteries-included behaviour — so the gap between expectation and reality feels larger. | |
| What Node.js could reasonably do but doesn't: | |
| spawn(cmd, { cleanup: true }) // hypothetical: sets PR_SET_PDEATHSIG automatically | |
| proc.killTree() // kills proc + all descendants recursively | |
| These would eliminate 90% of what we wrote. They don't exist. There are userland packages (tree-kill, execa with cleanup: true) that fill this gap. execa in particular handles | |
| cleanup, tree-kill, and cross-platform correctly — if qunitx weren't avoiding extra dependencies, it would eliminate most of this code. | |
| So: yes, the API is too thin and too close to raw syscalls for what most developers need. But the underlying complexity is real — Node.js inherited it rather than invented it, | |
| and just chose not to abstract it away. | |
| The BUG reference: (put the link here) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment