Make sure Error object on exec() gets killed member
Also default to SIGTERM for destruction when exceeding timeout or buffer on exec()
This commit is contained in:
parent
d9a5edb2b0
commit
9bf2975f78
@ -1068,14 +1068,14 @@ There is a second optional argument to specify several options. The default opti
|
|||||||
{ encoding: 'utf8'
|
{ encoding: 'utf8'
|
||||||
, timeout: 0
|
, timeout: 0
|
||||||
, maxBuffer: 200*1024
|
, maxBuffer: 200*1024
|
||||||
, killSignal: 'SIGKILL'
|
, killSignal: 'SIGTERM'
|
||||||
, cwd: null
|
, cwd: null
|
||||||
, env: null
|
, env: null
|
||||||
}
|
}
|
||||||
|
|
||||||
If `timeout` is greater than 0, then it will kill the child process
|
If `timeout` is greater than 0, then it will kill the child process
|
||||||
if it runs longer than `timeout` milliseconds. The child process is killed with
|
if it runs longer than `timeout` milliseconds. The child process is killed with
|
||||||
`killSignal` (default: `'SIGKILL'`). `maxBuffer` specifies the largest
|
`killSignal` (default: `'SIGTERM'`). `maxBuffer` specifies the largest
|
||||||
amount of data allowed on stdout or stderr - if this value is exceeded then
|
amount of data allowed on stdout or stderr - if this value is exceeded then
|
||||||
the child process is killed.
|
the child process is killed.
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ exports.execFile = function (file /* args, options, callback */) {
|
|||||||
var options = { encoding: 'utf8'
|
var options = { encoding: 'utf8'
|
||||||
, timeout: 0
|
, timeout: 0
|
||||||
, maxBuffer: 200*1024
|
, maxBuffer: 200*1024
|
||||||
, killSignal: 'SIGKILL'
|
, killSignal: 'SIGTERM'
|
||||||
, cwd: null
|
, cwd: null
|
||||||
, env: null
|
, env: null
|
||||||
};
|
};
|
||||||
@ -62,18 +62,24 @@ exports.execFile = function (file /* args, options, callback */) {
|
|||||||
var stderr = "";
|
var stderr = "";
|
||||||
var killed = false;
|
var killed = false;
|
||||||
var exited = false;
|
var exited = false;
|
||||||
|
var timeoutId;
|
||||||
|
|
||||||
function exithandler (code, signal) {
|
function exithandler (code, signal) {
|
||||||
if (timeoutId) clearTimeout(timeoutId);
|
|
||||||
if (exited) return;
|
if (exited) return;
|
||||||
exited = true;
|
exited = true;
|
||||||
|
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!callback) return;
|
if (!callback) return;
|
||||||
|
|
||||||
if (code === 0 && signal === null) {
|
if (code === 0 && signal === null) {
|
||||||
callback(null, stdout, stderr);
|
callback(null, stdout, stderr);
|
||||||
} else {
|
} else {
|
||||||
var e = new Error("Command failed: " + stderr);
|
var e = new Error("Command failed: " + stderr);
|
||||||
e.killed = killed;
|
e.killed = child.killed || killed;
|
||||||
e.code = code;
|
e.code = code;
|
||||||
e.signal = signal;
|
e.signal = signal;
|
||||||
callback(e, stdout, stderr);
|
callback(e, stdout, stderr);
|
||||||
@ -81,14 +87,13 @@ exports.execFile = function (file /* args, options, callback */) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function kill () {
|
function kill () {
|
||||||
var c = child.kill(options.killSignal);
|
|
||||||
killed = true;
|
killed = true;
|
||||||
|
child.kill(options.killSignal);
|
||||||
process.nextTick(function () {
|
process.nextTick(function () {
|
||||||
exithandler(null, options.killSignal)
|
exithandler(null, options.killSignal)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeoutId;
|
|
||||||
if (options.timeout > 0) {
|
if (options.timeout > 0) {
|
||||||
timeoutId = setTimeout(function () {
|
timeoutId = setTimeout(function () {
|
||||||
kill();
|
kill();
|
||||||
@ -113,8 +118,6 @@ exports.execFile = function (file /* args, options, callback */) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var pid = child.pid;
|
|
||||||
|
|
||||||
child.addListener("exit", exithandler);
|
child.addListener("exit", exithandler);
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
@ -126,6 +129,8 @@ function ChildProcess () {
|
|||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
this.killed = false;
|
||||||
|
|
||||||
var gotCHLD = false;
|
var gotCHLD = false;
|
||||||
var exitCode;
|
var exitCode;
|
||||||
var termSignal;
|
var termSignal;
|
||||||
@ -172,6 +177,7 @@ util.inherits(ChildProcess, EventEmitter);
|
|||||||
|
|
||||||
ChildProcess.prototype.kill = function (sig) {
|
ChildProcess.prototype.kill = function (sig) {
|
||||||
if (this._internal.pid) {
|
if (this._internal.pid) {
|
||||||
|
this.killed = true;
|
||||||
if (!constants) constants = process.binding("constants");
|
if (!constants) constants = process.binding("constants");
|
||||||
sig = sig || 'SIGTERM';
|
sig = sig || 'SIGTERM';
|
||||||
if (!constants[sig]) throw new Error("Unknown signal: " + sig);
|
if (!constants[sig]) throw new Error("Unknown signal: " + sig);
|
||||||
|
@ -44,7 +44,7 @@ exec("sleep 3", { timeout: 50 }, function (err, stdout, stderr) {
|
|||||||
assert.ok(diff < 500);
|
assert.ok(diff < 500);
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.ok(err.killed);
|
assert.ok(err.killed);
|
||||||
assert.equal(err.signal, 'SIGKILL');
|
assert.equal(err.signal, 'SIGTERM');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ function killMeTwiceCallback(err, stdout, stderr) {
|
|||||||
// parameters.
|
// parameters.
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.ok(err.killed);
|
assert.ok(err.killed);
|
||||||
assert.equal(err.signal, 'SIGKILL');
|
assert.equal(err.signal, 'SIGTERM');
|
||||||
|
|
||||||
// the timeout should still be in effect
|
// the timeout should still be in effect
|
||||||
console.log("'sleep 3' was already killed. Took %d ms", diff);
|
console.log("'sleep 3' was already killed. Took %d ms", diff);
|
||||||
@ -81,7 +81,7 @@ function killMeTwiceCallback(err, stdout, stderr) {
|
|||||||
exec('python -c "print 200000*\'C\'"', { maxBuffer: 1000 }, function (err, stdout, stderr) {
|
exec('python -c "print 200000*\'C\'"', { maxBuffer: 1000 }, function (err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.ok(err.killed);
|
assert.ok(err.killed);
|
||||||
assert.equal(err.signal, 'SIGKILL');
|
assert.equal(err.signal, 'SIGTERM');
|
||||||
});
|
});
|
||||||
|
|
||||||
process.addListener("exit", function () {
|
process.addListener("exit", function () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user