Browse Source

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.
v0.7.4-release
Andreas Madsen 13 years ago
committed by Bert Belder
parent
commit
836344c90e
  1. 14
      doc/api/child_processes.markdown
  2. 43
      lib/child_process.js

14
doc/api/child_processes.markdown

@ -24,6 +24,13 @@ of the signal, otherwise `null`.
See `waitpid(2)`.
### Event: 'disconnect'
This event is emitted after using the `.disconnect()` method in the parent or
in the child. After disconnecting it is no longer possible to send messages.
An alternative way to check if you can send messages is to see if the
`child.connected` property is `true`.
### child.stdin
A `Writable Stream` that represents the child process's `stdin`.
@ -264,7 +271,12 @@ processes:
}
});
To close the IPC connection between parent and child use the
`child.disconnect()` method. This allows the child to exit gracefully since
there is no IPC channel keeping it alive. When calling this method the
`disconnect` event will be emitted in both parent and child, and the
`connected` flag will be set to `false`. Please note that you can also call
`process.disconnect()` in the child process.
### child.kill([signal])

43
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;
};

Loading…
Cancel
Save