-
-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When killing the child process, kill all the descendants as well #170
Conversation
This is an attempt to fix the problem described by the issue sindresorhus#96. If a child process is killed, the descendents of that child process won't be killed as well. This happens on Linux but not on Windows [^1]. The adopted solution is the "PID range hack" [^2] that uses the `detached` mode for spawning a process and then kills that child process by killing the PID group, using `process.kill(-pid)`, effectively killing all the descendents. *Implementation* - added an internal option `killByPid` as a remained for the spawned child process that it will be `detached` and to kill it by PID - expanded and moved to a separate function the routine to kill the spawned process to `killSpawned` - the `ChildProcess#kill` method of the spawned child process will be replaced by the `killSpawned` routine, to kill by pid if necessary - the `killSpawned` routine signals that the child process has been killed, if it has been killed by the pid I checked and all the tests pass. This implementation also considers the issue sindresorhus#115 and shouldn't interfere with the detached/cleanup fix. [^1]: https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal [^2]: https://azimi.me/2014/12/31/kill-child_process-node-js.html
index.js
Outdated
spawned._kill(signal); | ||
} else { | ||
// Kills the spawned process and its descendents using the pid range hack | ||
// Source: https://azimi.me/2014/12/31/kill-child_process-node-js.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From reading the article, it looks like the PID trick only works when using {detached: true}
which we cannot assume.
This will needs tests. |
The PID hack requires I'm looking into simonepri/pidtree, a package similar to The basic implementation that comes to mind should go something like this: if it's Linux then use |
Which one of these implementation is better?
For the solution 1. |
Number 2, but |
@ehmicky Any opinions on this? |
I am wondering if the original problem was framed correctly because of two reasons: I.e. for me the question is about failure termination, either external (signals / |
True, so it would be better to leave that method alone and add a new one.
By a quick test I've made on Linux, to sum up:
On a practical note, on Linux, after a process has failed it leaves orphaned processes which can't be tracked as their PPID (which is the process PID) changes. We can't ensure killing the descendants once a process has failed. I'm also wondering if this problem could and should be addressed by As a spec to follow we could compare what Windows and what Linux do and don't do well in terms of sending signals and terminating the process and it's descedants. |
Yes you're right. I just checked it on Ubuntu and when a process is terminated, its still-running child processes become orphan, i.e. their It does not seem to be possible to know the original parent after it has exited. Which means it can only be done while the parent is still running, which we cannot guarantee on signal termination like Based on that I agree with @tomsotte that the best thing to do would be to limit this PR to an explicit method (like Note: it would be nice also if that method could re-use the extra |
For the As @sindresorhus said:
What do we do about those two other ways of killing the process? Should they remain intact? Should they honour the option
Yes, I might look into adding this as well. |
About using an option: I think we should either use an option with |
You're right on that. I'm also thinking that this addition will require a different library, something like |
Instead of having two different strategies:
Wouldn't it be simpler to use only 2), whether
|
Correct, it would be best to just use the 2) implementation as you said. The method might use I was also looking at |
I agree. I actually thought of |
I've been thinking about this PR and I actually think the following implementation might work better, let me know what you think: const childProcess = execa('echo');
childProcess.kill('SIGTERM', {deep: true}); childProcess.kill('SIGTERM', {deep: true, forceKillAfterTimeout: 5000});
When it comes to finding all descendants, I am actually wondering whether I am also starting to think that this feature belongs to a separate repository. Or sending a PR to any repository that already does something similar. This could be useful outside of |
The very reason I've started to look into this issue, that this PR is trying to fix, was that I was upset that on Windows the ChildProcess I agree with you that EDIT: If you feel the same we can close this PR. Thanks in advance for your time spent on this and as always I've appreciated your mentoring and your insights :) |
Yes I agree with you. I suggested using a I also agree that this is a useful feature but I do think the following might be better:
What do you think? |
|
@sindresorhus do you think we should implement this feature directly inside A third solution would be to separate the logic into a new library for this specific purpose (hence smaller). |
I think we should open an issue on Node.js about providing this built-in. |
Closing per previous discussion. Would be great if someone could open that Node.js issue and comment a link to it here. |
This is an attempt to fix the problem described by the issue #96.
If a child process is killed, the descendents of that child process won't be killed as well. This happens on Linux but not on Windows 1.
The adopted solution is the "PID range hack" 2 that uses the
detached
mode for spawning a process and then kills that child process by killing the PID group, usingprocess.kill(-pid)
, effectively killing all the descendents.Implementation
killByPid
as a reminder for the spawned child process that it will bedetached
and to kill it by PIDkillSpawned
ChildProcess#kill
method of the spawned child process will be replaced by thekillSpawned
routine, to kill by pid if necessarykillSpawned
routine signals that the child process has been killed, if it has been killed by the pidI checked and all the tests pass.
This implementation also considers the issue #115 and shouldn't interfere with the detached/cleanup fix.
Footnotes
https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal ↩
https://azimi.me/2014/12/31/kill-child_process-node-js.html ↩