diff options
author | Andreas Madsen <amwebdk@gmail.com> | 2012-01-30 19:35:05 +0400 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2012-01-30 19:35:27 +0400 |
commit | 836344c90ed139f2e18bbcfb18d0ff2e2e42da81 (patch) | |
tree | d06a79efa537b0968920cdb593611adeff4e1f9a /lib | |
parent | 52bd0f93bb786de028463ef56ddb1e22568584b9 (diff) |
Add disconnect method to forked child processes
This disconnect method allows the child to exit gracefully.
This also adds a disconnect event and connect property.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/child_process.js | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/lib/child_process.js b/lib/child_process.js index 9cdf7d6eecb..4af4d4f4139 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -85,6 +85,7 @@ function setupChannel(target, channel) { } } + channel.buffering = false; channel.onread = function(pool, offset, length, recvHandle) { if (recvHandle && setSimultaneousAccepts) { // Update simultaneous accepts on Windows @@ -117,10 +118,11 @@ function setupChannel(target, channel) { start = i + 1; } jsonBuffer = jsonBuffer.slice(start); + this.buffering = jsonBuffer.length !== 0; } else { - channel.close(); - target._channel = null; + this.buffering = false; + target.disconnect(); } }; @@ -129,7 +131,7 @@ function setupChannel(target, channel) { throw new TypeError('message cannot be undefined'); } - if (!target._channel) throw new Error("channel closed"); + if (!this.connected) throw new Error("channel closed"); // For overflow protection don't write if channel queue is too deep. if (channel.writeQueueSize > 1024 * 1024) { @@ -154,6 +156,34 @@ function setupChannel(target, channel) { return true; }; + target.connected = true; + target.disconnect = function() { + if (!this.connected) return; + + // do not allow messages to be written + this.connected = false; + this._channel = null; + + var fired = false; + function finish() { + if (fired) return; + fired = true; + + channel.close(); + target.emit('disconnect'); + } + + // If a message is being read, then wait for it to complete. + if (channel.buffering) { + this.once('message', finish); + this.once('internalMessage', finish); + + return; + } + + finish(); + }; + channel.readStart(); } @@ -201,11 +231,8 @@ exports.fork = function(modulePath /*, args, options*/) { if (!options.thread) setupChannel(child, options.stdinStream); - child.on('exit', function() { - if (child._channel) { - child._channel.close(); - } - }); + // Disconnect when the child process exits. + child.once('exit', child.disconnect.bind(child)); return child; }; |