Skip to content

Instantly share code, notes, and snippets.

@izelnakri
Created April 13, 2026 08:40
Show Gist options
  • Select an option

  • Save izelnakri/5a7f25ab01940f915b01754585ddeac1 to your computer and use it in GitHub Desktop.

Select an option

Save izelnakri/5a7f25ab01940f915b01754585ddeac1 to your computer and use it in GitHub Desktop.
Major Node.js BUG: process management/children resources
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