diff --git a/doc/api.markdown b/doc/api.markdown index 32e9b0c6a1a..5f7f141933b 100644 --- a/doc/api.markdown +++ b/doc/api.markdown @@ -1068,14 +1068,14 @@ There is a second optional argument to specify several options. The default opti { encoding: 'utf8' , timeout: 0 , maxBuffer: 200*1024 - , killSignal: 'SIGKILL' + , killSignal: 'SIGTERM' , cwd: null , env: null } 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 -`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 the child process is killed. diff --git a/lib/child_process.js b/lib/child_process.js index e0d816a740e..342b050f666 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -28,7 +28,7 @@ exports.execFile = function (file /* args, options, callback */) { var options = { encoding: 'utf8' , timeout: 0 , maxBuffer: 200*1024 - , killSignal: 'SIGKILL' + , killSignal: 'SIGTERM' , cwd: null , env: null }; @@ -62,18 +62,24 @@ exports.execFile = function (file /* args, options, callback */) { var stderr = ""; var killed = false; var exited = false; + var timeoutId; function exithandler (code, signal) { - if (timeoutId) clearTimeout(timeoutId); if (exited) return; exited = true; + + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (!callback) return; if (code === 0 && signal === null) { callback(null, stdout, stderr); } else { var e = new Error("Command failed: " + stderr); - e.killed = killed; + e.killed = child.killed || killed; e.code = code; e.signal = signal; callback(e, stdout, stderr); @@ -81,14 +87,13 @@ exports.execFile = function (file /* args, options, callback */) { } function kill () { - var c = child.kill(options.killSignal); killed = true; + child.kill(options.killSignal); process.nextTick(function () { exithandler(null, options.killSignal) }); } - var timeoutId; if (options.timeout > 0) { timeoutId = setTimeout(function () { kill(); @@ -113,8 +118,6 @@ exports.execFile = function (file /* args, options, callback */) { } }); - var pid = child.pid; - child.addListener("exit", exithandler); return child; @@ -126,6 +129,8 @@ function ChildProcess () { var self = this; + this.killed = false; + var gotCHLD = false; var exitCode; var termSignal; @@ -172,6 +177,7 @@ util.inherits(ChildProcess, EventEmitter); ChildProcess.prototype.kill = function (sig) { if (this._internal.pid) { + this.killed = true; if (!constants) constants = process.binding("constants"); sig = sig || 'SIGTERM'; if (!constants[sig]) throw new Error("Unknown signal: " + sig); diff --git a/test/simple/test-exec.js b/test/simple/test-exec.js index 8819bd12621..f4f3cf87308 100644 --- a/test/simple/test-exec.js +++ b/test/simple/test-exec.js @@ -44,7 +44,7 @@ exec("sleep 3", { timeout: 50 }, function (err, stdout, stderr) { assert.ok(diff < 500); assert.ok(err); assert.ok(err.killed); - assert.equal(err.signal, 'SIGKILL'); + assert.equal(err.signal, 'SIGTERM'); }); @@ -69,7 +69,7 @@ function killMeTwiceCallback(err, stdout, stderr) { // parameters. assert.ok(err); assert.ok(err.killed); - assert.equal(err.signal, 'SIGKILL'); + assert.equal(err.signal, 'SIGTERM'); // the timeout should still be in effect 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) { assert.ok(err); assert.ok(err.killed); - assert.equal(err.signal, 'SIGKILL'); + assert.equal(err.signal, 'SIGTERM'); }); process.addListener("exit", function () {