Browse Source

Prevents child_process.exec timeouts from throwing when the child was previously killed.

v0.7.4-release
Aaron Heckmann 14 years ago
committed by Ryan Dahl
parent
commit
bd8e4f656e
  1. 34
      lib/child_process.js
  2. 13
      test/simple/test-exec.js

34
lib/child_process.js

@ -62,14 +62,23 @@ exports.execFile = function (file /* args, options, callback */) {
var stderr = ""; var stderr = "";
var killed = false; var killed = false;
function kill(){
if (killed) return;
try {
child.kill(options.killSignal);
} catch (err) {
if ("No such process" !== err.message) {
throw err;
}
}
killed = true;
}
var timeoutId; var timeoutId;
if (options.timeout > 0) { if (options.timeout > 0) {
timeoutId = setTimeout(function () { timeoutId = setTimeout(function () {
if (!killed) { kill();
child.kill(options.killSignal); timeoutId = null;
killed = true;
timeoutId = null;
}
}, options.timeout); }, options.timeout);
} }
@ -78,30 +87,29 @@ exports.execFile = function (file /* args, options, callback */) {
child.stdout.addListener("data", function (chunk) { child.stdout.addListener("data", function (chunk) {
stdout += chunk; stdout += chunk;
if (!killed && stdout.length > options.maxBuffer) { if (stdout.length > options.maxBuffer) {
child.kill(options.killSignal); kill();
killed = true;
} }
}); });
child.stderr.addListener("data", function (chunk) { child.stderr.addListener("data", function (chunk) {
stderr += chunk; stderr += chunk;
if (!killed && stderr.length > options.maxBuffer) { if (stderr.length > options.maxBuffer) {
child.kill(options.killSignal); kill();
killed = true;
} }
}); });
child.addListener("exit", function (code, signal) { child.addListener("exit", function (code, signal) {
if (timeoutId) clearTimeout(timeoutId); if (timeoutId) clearTimeout(timeoutId);
if (!callback) return;
if (code === 0 && signal === null) { if (code === 0 && signal === null) {
if (callback) 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 = killed;
e.code = code; e.code = code;
e.signal = signal; e.signal = signal;
if (callback) callback(e, stdout, stderr); callback(e, stdout, stderr);
} }
}); });

13
test/simple/test-exec.js

@ -35,12 +35,23 @@ exec("ls /DOES_NOT_EXIST", function (err, stdout, stderr) {
} }
}); });
exec("sleep 10", { timeout: 50 }, function (err, stdout, stderr) { exec("sleep 3", { timeout: 50 }, 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, 'SIGKILL');
}); });
var killMeTwice = exec("sleep 3", { timeout: 1000 }, function killMeTwiceCallback(err, stdout, stderr) {
assert.ok(err);
assert.ok(err.killed);
assert.equal(err.signal, 'SIGTERM');
});
process.nextTick(function(){
killMeTwice.kill();
});
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);

Loading…
Cancel
Save