Support sending handles to other processes
authorRyan Dahl <ry@tinyclouds.org>
Fri, 7 Oct 2011 08:30:26 +0000 (01:30 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Fri, 7 Oct 2011 08:30:28 +0000 (01:30 -0700)
Needs test.

doc/api/child_processes.markdown
lib/child_process_uv.js
src/stream_wrap.cc

index eb0a701f9017a46a039dd96e9a979dc20796cfe5..495e65e5bbd32c83333d5f51abbbc58e6eb1b0ee 100644 (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
 processes. In addition to having all the methods in a normal ChildProcess
 instance, the returned object has a communication channel built-in. The
-channel is written to with `child.send(message)` and messages are recieved
-by a `'message'` event on the child.
+channel is written to with `child.send(message, [sendStream])` and messages
+are recieved by a `'message'` event on the child.
 
 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
 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')
 
index 3dbe5f11b77bbc6dad6e39485ffa1a5f5b398ada..916301002d6ea5ccb1f27fe5da5f115268408b83 100644 (file)
@@ -73,7 +73,7 @@ function setupChannel(target, channel) {
 
   var jsonBuffer = '';
 
-  channel.onread = function(pool, offset, length) {
+  channel.onread = function(pool, offset, length, recvStream) {
     if (pool) {
       for (var i = 0; i < length; i++) {
         if (pool[offset + i] === LF) {
@@ -82,7 +82,7 @@ function setupChannel(target, channel) {
           jsonBuffer = pool.toString('ascii', i, length);
           offset = i + 1;
 
-          target.emit('message', message);
+          target.emit('message', message, recvStream);
         }
       }
     } else {
@@ -91,11 +91,14 @@ function setupChannel(target, channel) {
     }
   };
 
-  target.send = function(message, fd) {
-    if (fd) throw new Error("not yet implemented");
-
+  target.send = function(message, sendStream) {
     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.
     if (channel.writeQueueSize > 1024 * 1024) {
       return false; 
@@ -103,7 +106,7 @@ function setupChannel(target, channel) {
 
     var buffer = Buffer(JSON.stringify(message) + '\n');
 
-    var writeReq = channel.write(buffer);
+    var writeReq = channel.write(buffer, 0, buffer.length, sendStream);
 
     if (!writeReq) {
       throw new Error(errno + " cannot write to IPC channel.");
index 548f978987048a49bb7828f41327275fda5af1ba..ab92e5668d5f9ee449ce1f21895400f66f056601 100644 (file)
@@ -292,8 +292,7 @@ Handle<Value> StreamWrap::Write(const Arguments& args) {
   } else {
     uv_stream_t* send_stream = NULL;
 
-    if (args.Length() > 3) {
-      assert(args[3]->IsObject());
+    if (args[3]->IsObject()) {
       Local<Object> send_stream_obj = args[3]->ToObject();
       assert(send_stream_obj->InternalFieldCount() > 0);
       StreamWrap* send_stream_wrap = static_cast<StreamWrap*>(