mirror of https://github.com/nodejs/node.git
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.pull/5370/head
parent
52bd0f93bb
commit
836344c90e
|
@ -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])
|
||||
|
||||
|
|
|
@ -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…
Reference in New Issue