Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Child process not getting killed with Node.JS

I used child_process.exec / child_process.spawn to fork a new process and then kill it using child.kill / process.kill. It works fine with simple binary executables, such as cat / ls, and the child process just get killed.

However, when get to the scripts (say P1) that forks another child process (say P2), only the script interpreter P1 get killed, not the child process P2.

QUESTION: is there any way that getting such child process P2 killed with Node.JS?

Code works fine with run_and_kill('ls -Al /usr/lib'), but not OK with run_and_kill('firefox'):

function run_and_kill(cmd) {
    var exec = require('child_process').exec,
        ls = exec(cmd);
    console.log('Child process started: %d', ls.pid);
    ls.on('exit', function(code, signal) {
        console.log('exit with code %s and signal %s', code, signal);
    });
    ls.kill();
}
like image 210
Ghostoy Avatar asked Jul 26 '11 03:07

Ghostoy


3 Answers

The safest way I've found to achieve this is creating a spawn process to kill the signal, using the child.pid as argument. Example with fork :

var process;
process = require('child_process');

var fork, child;
fork = process.fork;
child = fork('./index');

var spawn;
spawn = process.spawn;
spawn('kill', [child.pid]);
console.log('sending SIGTERM to child process (socket server)');

I typically use this in specs, mostly in beforeAll/afterAll blocks to start/kill servers (in the example './index.js').

like image 157
Francisco Avatar answered Oct 07 '22 17:10

Francisco


I think your P2 is neither a fork or a child of P1 but rather a parallel process spawned by it. In the case of Firefox ( at least in Linux ) the firefox app is launched by a wrapper shell script. If it's always going to be firefox, better run the binary straight from it's install folder

like image 32
Rilke Petrosky Avatar answered Oct 07 '22 17:10

Rilke Petrosky


In my case the problem was the shell being used for the process. By default it's /bin/sh, and when this was being used it wasn't handling the kill signals.

To fix this you can use /bin/bash instead:

exec('your command', {
    shell: '/bin/bash',
});
like image 34
dspacejs Avatar answered Oct 07 '22 17:10

dspacejs