Skip to content

Commit bd8e4f6

Browse files
aheckmannry
authored andcommitted
Prevents child_process.exec timeouts from throwing when the child was previously killed.
1 parent 226eff5 commit bd8e4f6

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

lib/child_process.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,23 @@ exports.execFile = function (file /* args, options, callback */) {
6262
var stderr = "";
6363
var killed = false;
6464

65+
function kill(){
66+
if (killed) return;
67+
try {
68+
child.kill(options.killSignal);
69+
} catch (err) {
70+
if ("No such process" !== err.message) {
71+
throw err;
72+
}
73+
}
74+
killed = true;
75+
}
76+
6577
var timeoutId;
6678
if (options.timeout > 0) {
6779
timeoutId = setTimeout(function () {
68-
if (!killed) {
69-
child.kill(options.killSignal);
70-
killed = true;
71-
timeoutId = null;
72-
}
80+
kill();
81+
timeoutId = null;
7382
}, options.timeout);
7483
}
7584

@@ -78,30 +87,29 @@ exports.execFile = function (file /* args, options, callback */) {
7887

7988
child.stdout.addListener("data", function (chunk) {
8089
stdout += chunk;
81-
if (!killed && stdout.length > options.maxBuffer) {
82-
child.kill(options.killSignal);
83-
killed = true;
90+
if (stdout.length > options.maxBuffer) {
91+
kill();
8492
}
8593
});
8694

8795
child.stderr.addListener("data", function (chunk) {
8896
stderr += chunk;
89-
if (!killed && stderr.length > options.maxBuffer) {
90-
child.kill(options.killSignal);
91-
killed = true;
97+
if (stderr.length > options.maxBuffer) {
98+
kill();
9299
}
93100
});
94101

95102
child.addListener("exit", function (code, signal) {
96103
if (timeoutId) clearTimeout(timeoutId);
104+
if (!callback) return;
97105
if (code === 0 && signal === null) {
98-
if (callback) callback(null, stdout, stderr);
106+
callback(null, stdout, stderr);
99107
} else {
100108
var e = new Error("Command failed: " + stderr);
101109
e.killed = killed;
102110
e.code = code;
103111
e.signal = signal;
104-
if (callback) callback(e, stdout, stderr);
112+
callback(e, stdout, stderr);
105113
}
106114
});
107115

test/simple/test-exec.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,23 @@ exec("ls /DOES_NOT_EXIST", function (err, stdout, stderr) {
3535
}
3636
});
3737

38-
exec("sleep 10", { timeout: 50 }, function (err, stdout, stderr) {
38+
exec("sleep 3", { timeout: 50 }, function (err, stdout, stderr) {
3939
assert.ok(err);
4040
assert.ok(err.killed);
4141
assert.equal(err.signal, 'SIGKILL');
4242
});
4343

44+
45+
var killMeTwice = exec("sleep 3", { timeout: 1000 }, function killMeTwiceCallback(err, stdout, stderr) {
46+
assert.ok(err);
47+
assert.ok(err.killed);
48+
assert.equal(err.signal, 'SIGTERM');
49+
});
50+
process.nextTick(function(){
51+
killMeTwice.kill();
52+
});
53+
54+
4455
exec('python -c "print 200000*\'C\'"', { maxBuffer: 1000 }, function (err, stdout, stderr) {
4556
assert.ok(err);
4657
assert.ok(err.killed);

0 commit comments

Comments
 (0)