Skip to content
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

Closed
wants to merge 8 commits into from
Closed
5 changes: 5 additions & 0 deletions fixtures/descendant
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node
'use strict';
const { spawn } = require('child_process');

console.log(spawn('forever').pid);
11 changes: 11 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,17 @@ const execa = (command, args, options) => {
}
};

spawned._kill = spawned.kill;
spawned.kill = signal => {
if (process.platform === 'win32') {
return spawned._kill(signal);
}

return spawned._kill(signal);
// TODO kill with pidtree
// do not kill this process via pidtree, exclude this PID?
};

// TOOD: Remove the `if`-guard when targeting Node.js 10
if (Promise.prototype.finally) {
spawned.finally = onFinally => handlePromise().finally(onFinally);
Expand Down
23 changes: 23 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,29 @@ if (process.platform !== 'win32') {
test('cleanup false - SIGKILL', spawnAndKill, 'SIGKILL', false);
}

test('when killing the child process, kill all its descendants as well', async t => {
const cp = execa('descendant');
let descendantPid;

cp.stdout.setEncoding('utf8');
cp.stdout.on('data', chunk => {
descendantPid = parseInt(chunk, 10);
t.is(typeof descendantPid, 'number');

setTimeout(() => {
cp.kill();
}, 100);
});

await t.throwsAsync(cp);

// Give everybody some time to breath and kill things
// await delay(200);

t.false(isRunning(cp.pid));
t.false(isRunning(descendantPid));
});

test('execa.shell() supports the `shell` option', async t => {
const {stdout} = await execa.shell('node fixtures/noop foo', {
shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash'
Expand Down