src: don't kill own process group on failed spawn - #65054
Conversation
1c77865 to
38627f1
Compare
Codecov Reportβ
All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #65054 +/- ##
==========================================
- Coverage 90.01% 89.99% -0.02%
==========================================
Files 757 757
Lines 257739 257740 +1
Branches 48882 48890 +8
==========================================
- Hits 232001 231956 -45
- Misses 16844 16865 +21
- Partials 8894 8919 +25
π New features to boost your workflow:
|
This comment was marked as resolved.
This comment was marked as resolved.
libuv only assigns a pid to the process handle once uv_spawn() has succeeded, so a child that never started keeps pid 0. Calling kill() on such a child still reached uv_process_kill(), which ended up in kill(0, signal) and signalled every process in the caller's own process group, Node included. Return ESRCH when the handle has no pid, and zero the pid in the constructor so the check never reads an unassigned value. Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com>
3174c46 to
2eeec11
Compare
|
Thanks, rebased. The branch now sits on top of New head: |
Commit Queue failedThe pull request was removed from the Commit Queue and labeled
commit-queue-failed
Full Commit Queue output |
libuv only assigns a pid to the process handle once
uv_spawn()succeeds, so a child that never started keeps pid 0. Callingkill()on that child still reacheduv_process_kill(), which ended up inkill(0, signal)and signalled every process in the caller's own process group, Node included. The handle is now reported asESRCHwhen there is no pid, sochild.kill()just returns false. The pid is also zeroed in the constructor so the check never reads an unassigned value.Reproducing it on its own needs no prototype tampering:
In the report the spawn failed for a different reason: overriding
Array.prototype[Symbol.iterator]makesnormalizeSpawnArguments()build an empty env, so the command was no longer found through PATH. The dead handle is what took the parent down.Behavior change
kill()on a child that failed to spawn used to returntrueon POSIX. It now returnsfalse.Windows was never affected by the process-group problem, since
uv_process_kill()bails out withEINVALwhen the handle has no process handle. It reached thethrow new ErrnoException(err, 'kill')branch instead, so therekill()goes from throwingEINVALto returningfalse. Both platforms now agree.subprocess.killedis also left alone in this case, which matches what the docs already say about it being set only when a signal is sent successfully.Fixes: #65052