Support sending handles to other processes

Needs test.
This commit is contained in:
Ryan Dahl 2011-10-07 01:30:26 -07:00
parent d2ab314e08
commit b413c77583
3 changed files with 16 additions and 10 deletions

View File

@ -190,8 +190,8 @@ leaner than `child_process.exec`. It has the same options.
This is a special case of the `spawn()` functionality for spawning Node This is a special case of the `spawn()` functionality for spawning Node
processes. In addition to having all the methods in a normal ChildProcess processes. In addition to having all the methods in a normal ChildProcess
instance, the returned object has a communication channel built-in. The instance, the returned object has a communication channel built-in. The
channel is written to with `child.send(message)` and messages are recieved channel is written to with `child.send(message, [sendStream])` and messages
by a `'message'` event on the child. are recieved by a `'message'` event on the child.
For example: For example:
@ -224,6 +224,10 @@ These child Nodes are still whole new instances of V8. Assume at least 30ms
startup and 10mb memory for each new Node. That is, you cannot create many startup and 10mb memory for each new Node. That is, you cannot create many
thousands of them. thousands of them.
The `sendStream` option to `child.send()` is for sending a `net.Socket`
or `net.Server` object to another process. Child will receive the handle as
as second argument to the `message` event.
### child.kill(signal='SIGTERM') ### child.kill(signal='SIGTERM')

View File

@ -73,7 +73,7 @@ function setupChannel(target, channel) {
var jsonBuffer = ''; var jsonBuffer = '';
channel.onread = function(pool, offset, length) { channel.onread = function(pool, offset, length, recvStream) {
if (pool) { if (pool) {
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
if (pool[offset + i] === LF) { if (pool[offset + i] === LF) {
@ -82,7 +82,7 @@ function setupChannel(target, channel) {
jsonBuffer = pool.toString('ascii', i, length); jsonBuffer = pool.toString('ascii', i, length);
offset = i + 1; offset = i + 1;
target.emit('message', message); target.emit('message', message, recvStream);
} }
} }
} else { } else {
@ -91,11 +91,14 @@ function setupChannel(target, channel) {
} }
}; };
target.send = function(message, fd) { target.send = function(message, sendStream) {
if (fd) throw new Error("not yet implemented");
if (!target._channel) throw new Error("channel closed"); if (!target._channel) throw new Error("channel closed");
// Open up net.Socket instances
if (sendStream instanceof require('net').Socket) {
sendStream = sendStream._handle;
}
// For overflow protection don't write if channel queue is too deep. // For overflow protection don't write if channel queue is too deep.
if (channel.writeQueueSize > 1024 * 1024) { if (channel.writeQueueSize > 1024 * 1024) {
return false; return false;
@ -103,7 +106,7 @@ function setupChannel(target, channel) {
var buffer = Buffer(JSON.stringify(message) + '\n'); var buffer = Buffer(JSON.stringify(message) + '\n');
var writeReq = channel.write(buffer); var writeReq = channel.write(buffer, 0, buffer.length, sendStream);
if (!writeReq) { if (!writeReq) {
throw new Error(errno + " cannot write to IPC channel."); throw new Error(errno + " cannot write to IPC channel.");

View File

@ -292,8 +292,7 @@ Handle<Value> StreamWrap::Write(const Arguments& args) {
} else { } else {
uv_stream_t* send_stream = NULL; uv_stream_t* send_stream = NULL;
if (args.Length() > 3) { if (args[3]->IsObject()) {
assert(args[3]->IsObject());
Local<Object> send_stream_obj = args[3]->ToObject(); Local<Object> send_stream_obj = args[3]->ToObject();
assert(send_stream_obj->InternalFieldCount() > 0); assert(send_stream_obj->InternalFieldCount() > 0);
StreamWrap* send_stream_wrap = static_cast<StreamWrap*>( StreamWrap* send_stream_wrap = static_cast<StreamWrap*>(