Browse Source

child_process: Separate 'close' event from 'exit'

Currently, a child process does not emit the 'exit' event until 'close' events
have been received on all three of the child's stdio streams.  This change makes
the child object emit 'exit' when the child exits, and a new 'close' event when
all stdio streams are closed.
v0.9.1-release
Charlie McConnell 13 years ago
committed by isaacs
parent
commit
c7b8073afc
  1. 14
      lib/child_process.js
  2. 9
      test/simple/test-child-process-buffering.js
  3. 5
      test/simple/test-child-process-cwd.js
  4. 6
      test/simple/test-child-process-stdin.js

14
lib/child_process.js

@ -341,7 +341,7 @@ exports.execFile = function(file /* args, options, callback */) {
}
});
child.addListener('exit', exithandler);
child.addListener('close', exithandler);
return child;
};
@ -373,11 +373,11 @@ var spawn = exports.spawn = function(file, args, options) {
};
function maybeExit(subprocess) {
function maybeClose(subprocess) {
subprocess._closesGot++;
if (subprocess._closesGot == subprocess._closesNeeded) {
subprocess.emit('exit', subprocess.exitCode, subprocess.signalCode);
subprocess.emit('close', subprocess.exitCode, subprocess.signalCode);
}
}
@ -413,7 +413,9 @@ function ChildProcess() {
self._internal.close();
self._internal = null;
maybeExit(self);
self.emit('exit', self.exitCode, self.signalCode);
maybeClose(self);
};
}
util.inherits(ChildProcess, EventEmitter);
@ -474,7 +476,7 @@ ChildProcess.prototype.spawn = function(options) {
this.stdout = createSocket(options.stdoutStream, true);
this._closesNeeded++;
this.stdout.on('close', function() {
maybeExit(self);
maybeClose(self);
});
}
@ -482,7 +484,7 @@ ChildProcess.prototype.spawn = function(options) {
this.stderr = createSocket(options.stderrStream, true);
this._closesNeeded++;
this.stderr.on('close', function() {
maybeExit(self);
maybeClose(self);
});
}

9
test/simple/test-child-process-buffering.js

@ -25,6 +25,8 @@ var assert = require('assert');
var spawn = require('child_process').spawn;
var pwd_called = false;
var childClosed = false;
var childExited = false;
function pwd(callback) {
var output = '';
@ -39,8 +41,13 @@ function pwd(callback) {
child.on('exit', function(c) {
console.log('exit: ' + c);
assert.equal(0, c);
childExited = true;
});
child.on('close', function () {
callback(output);
pwd_called = true;
childClosed = true;
});
}
@ -53,4 +60,6 @@ pwd(function(result) {
process.on('exit', function() {
assert.equal(true, pwd_called);
assert.equal(true, childExited);
assert.equal(true, childClosed);
});

5
test/simple/test-child-process-cwd.js

@ -44,8 +44,11 @@ function testCwd(options, forCode, forData) {
});
child.on('exit', function(code, signal) {
forData && assert.strictEqual(forData, data.replace(/[\s\r\n]+$/, ''));
assert.strictEqual(forCode, code);
});
child.on('close', function () {
forData && assert.strictEqual(forData, data.replace(/[\s\r\n]+$/, ''));
returns--;
});

6
test/simple/test-child-process-stdin.js

@ -37,6 +37,7 @@ cat.stdin.end();
var response = '';
var exitStatus = -1;
var closed = false;
var gotStdoutEOF = false;
@ -66,6 +67,10 @@ cat.stderr.on('end', function(chunk) {
cat.on('exit', function(status) {
console.log('exit event');
exitStatus = status;
});
cat.on('close', function () {
closed = true;
if (is_windows) {
assert.equal('hello world\r\n', response);
} else {
@ -75,6 +80,7 @@ cat.on('exit', function(status) {
process.on('exit', function() {
assert.equal(0, exitStatus);
assert(closed);
if (is_windows) {
assert.equal('hello world\r\n', response);
} else {

Loading…
Cancel
Save