Fix execFile timeouts, improve tests
It seems that a parent will not get a SIGCHLD if the child is killed by the parent? It's unclear, so make 'exit' callback manually.
This commit is contained in:
parent
5a98fa4809
commit
6570cd99e5
@ -61,10 +61,31 @@ exports.execFile = function (file /* args, options, callback */) {
|
|||||||
var stdout = "";
|
var stdout = "";
|
||||||
var stderr = "";
|
var stderr = "";
|
||||||
var killed = false;
|
var killed = false;
|
||||||
|
var exited = false;
|
||||||
|
|
||||||
|
function exithandler (code, signal) {
|
||||||
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
|
if (exited) return;
|
||||||
|
exited = true;
|
||||||
|
if (!callback) return;
|
||||||
|
|
||||||
|
if (code === 0 && signal === null) {
|
||||||
|
callback(null, stdout, stderr);
|
||||||
|
} else {
|
||||||
|
var e = new Error("Command failed: " + stderr);
|
||||||
|
e.killed = killed;
|
||||||
|
e.code = code;
|
||||||
|
e.signal = signal;
|
||||||
|
callback(e, stdout, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function kill () {
|
function kill () {
|
||||||
child.kill(options.killSignal);
|
var c = child.kill(options.killSignal);
|
||||||
killed = true;
|
killed = true;
|
||||||
|
process.nextTick(function () {
|
||||||
|
exithandler(null, options.killSignal)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeoutId;
|
var timeoutId;
|
||||||
@ -92,19 +113,9 @@ exports.execFile = function (file /* args, options, callback */) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
child.addListener("exit", function (code, signal) {
|
var pid = child.pid;
|
||||||
if (timeoutId) clearTimeout(timeoutId);
|
|
||||||
if (!callback) return;
|
child.addListener("exit", exithandler);
|
||||||
if (code === 0 && signal === null) {
|
|
||||||
callback(null, stdout, stderr);
|
|
||||||
} else {
|
|
||||||
var e = new Error("Command failed: " + stderr);
|
|
||||||
e.killed = killed;
|
|
||||||
e.code = code;
|
|
||||||
e.signal = signal;
|
|
||||||
callback(e, stdout, stderr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
};
|
};
|
||||||
|
@ -35,22 +35,48 @@ exec("ls /DOES_NOT_EXIST", function (err, stdout, stderr) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var sleeperStart = new Date();
|
||||||
exec("sleep 3", { timeout: 50 }, function (err, stdout, stderr) {
|
exec("sleep 3", { timeout: 50 }, function (err, stdout, stderr) {
|
||||||
|
var diff = (new Date()) - sleeperStart;
|
||||||
|
console.log("sleep 3 with timeout 50 took %d ms", diff);
|
||||||
|
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, 'SIGKILL');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var killMeTwice = exec("sleep 3", { timeout: 1000 }, function killMeTwiceCallback(err, stdout, stderr) {
|
|
||||||
assert.ok(err);
|
|
||||||
assert.ok(err.killed);
|
var startSleep3 = new Date();
|
||||||
assert.equal(err.signal, 'SIGTERM');
|
var killMeTwice = exec("sleep 3", { timeout: 1000 }, killMeTwiceCallback);
|
||||||
});
|
|
||||||
process.nextTick(function(){
|
process.nextTick(function(){
|
||||||
|
console.log("kill pid %d", killMeTwice.pid);
|
||||||
|
// make sure there is no race condition in starting the process
|
||||||
|
// the PID SHOULD exist directly following the exec() call.
|
||||||
|
assert.equal('number', typeof killMeTwice._internal.pid);
|
||||||
|
// Kill the process
|
||||||
killMeTwice.kill();
|
killMeTwice.kill();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function killMeTwiceCallback(err, stdout, stderr) {
|
||||||
|
var diff = (new Date()) - startSleep3;
|
||||||
|
// We should have already killed this process. Assert that
|
||||||
|
// the timeout still works and that we are getting the proper callback
|
||||||
|
// parameters.
|
||||||
|
assert.ok(err);
|
||||||
|
assert.ok(err.killed);
|
||||||
|
assert.equal(err.signal, 'SIGKILL');
|
||||||
|
|
||||||
|
// the timeout should still be in effect
|
||||||
|
console.log("'sleep 3' was already killed. Took %d ms", diff);
|
||||||
|
assert.ok(diff < 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user