36

How to kill all child processes (spawned using child_process.spawn) when node.js process exit?

Sirian
  • 768
  • 1
  • 6
  • 10

2 Answers2

34

I think the only way is to keep a reference to the ChildProcess object returned by spawn, and kill it when you exit the master process.

A small example:

var spawn     = require('child_process').spawn;
var children  = [];

process.on('exit', function() {
  console.log('killing', children.length, 'child processes');
  children.forEach(function(child) {
    child.kill();
  });
});

children.push(spawn('/bin/sleep', [ '10' ]));
children.push(spawn('/bin/sleep', [ '10' ]));
children.push(spawn('/bin/sleep', [ '10' ]));

setTimeout(function() { process.exit(0) }, 3000);
robertklep
  • 174,329
  • 29
  • 336
  • 330
  • on my mac, any childprocesses started by spawn get killed when the main node process finishes. Perhaps this is OS specific? – AndyD Apr 05 '13 at 15:06
  • 1
    On my Mac (10.8.3) they keep going: with the code above, when I comment out `child.kill()`, I briefly (until the 10 seconds are up) see three `sleep` processes in the output of `ps` after the master process has stopped (although those processes are connected to the controller terminal of the shell; when I kill the shell, they are gone). – robertklep Apr 05 '13 at 15:40
  • 1
    Interesting. My child process is a phantomjs process. Perhaps that behaves differently. I'll use the above code if it ever changes. (10.8.0) – AndyD Apr 05 '13 at 19:36
  • what version of node are you using? – AndyD Apr 05 '13 at 19:37
  • Both 0.10.1 and 0.8.16, same behaviour :) – robertklep Apr 05 '13 at 19:43
  • What happens if you set the timeout to 20000? This would guarantee that each child process would have finished. Would `child.kill()` then attempt to kill some other process on the system that was reassigned the PID of the child process? – Sukima Feb 07 '14 at 02:24
  • 2
    @Sukima [the fine manual](http://nodejs.org/api/child_process.html#child_process_child_kill_signal) states: *"Sending a signal to a child process that has already exited is not an error but may have unforeseen consequences: if the PID (the process ID) has been reassigned to another process, the signal will be delivered to that process instead"*. So yes, it *may* kill an unrelated process. – robertklep Feb 07 '14 at 07:23
  • 1
    @robertklep That's what I though. Sounds bad. Any advise on preventing that in the above code example? – Sukima Feb 07 '14 at 17:14
33

To add to @robertklep's answer:

If, like me, you want to do this when Node is being killed externally, rather than of its own choice, you have to do some trickery with signals.

The key is to listen for whatever signal(s) you could be killed with, and call process.exit(), otherwise Node by default won't emit exit on process!

var cleanExit = function() { process.exit() };
process.on('SIGINT', cleanExit); // catch ctrl-c
process.on('SIGTERM', cleanExit); // catch kill

After doing this, you can just listen to exit on process normally.

The only issue is SIGKILL can't be caught, but that's by design. You should be killing with SIGTERM (the default) anyway.

See this question for more.

Community
  • 1
  • 1
DuBistKomisch
  • 826
  • 10
  • 8