diff --git a/lib/child_process.js b/lib/child_process.js index e67615d21b..e4fe26ecda 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -24,6 +24,7 @@ var EventEmitter = require('events').EventEmitter; var net = require('net'); var dgram = require('dgram'); var Process = process.binding('process_wrap').Process; +var assert = require('assert'); var util = require('util'); var constants; // if (!constants) constants = process.binding('constants'); @@ -321,6 +322,7 @@ function handleMessage(target, message, handle) { function setupChannel(target, channel) { target._channel = channel; + target._handleQueue = null; var decoder = new StringDecoder('utf8'); var jsonBuffer = ''; @@ -358,8 +360,22 @@ function setupChannel(target, channel) { // handlers will go through this target.on('internalMessage', function(message, handle) { + // Once acknowledged - continue sending handles. + if (message.cmd === 'NODE_HANDLE_ACK') { + assert(Array.isArray(target._handleQueue)); + var queue = target._handleQueue; + target._handleQueue = null; + queue.forEach(function(args) { + target.send(args.message, args.handle); + }); + return; + } + if (message.cmd !== 'NODE_HANDLE') return; + // Acknowledge handle receival. + target.send({ cmd: 'NODE_HANDLE_ACK' }); + var obj = handleConversion[message.type]; // Update simultaneous accepts on Windows @@ -389,6 +405,7 @@ function setupChannel(target, channel) { // this message will be handled by an internalMessage event handler message = { cmd: 'NODE_HANDLE', + type: null, msg: message }; @@ -407,6 +424,12 @@ function setupChannel(target, channel) { throw new TypeError("This handle type can't be sent"); } + // Queue-up message and handle if we haven't received ACK yet. + if (this._handleQueue) { + this._handleQueue.push({ message: message.msg, handle: handle }); + return; + } + var obj = handleConversion[message.type]; // convert TCP object to native handle object @@ -416,6 +439,10 @@ function setupChannel(target, channel) { if (obj.simultaneousAccepts) { net._setSimultaneousAccepts(handle); } + } else if (this._handleQueue) { + // Queue request anyway to avoid out-of-order messages. + this._handleQueue.push({ message: message, handle: null }); + return; } var string = JSON.stringify(message) + '\n'; @@ -426,6 +453,8 @@ function setupChannel(target, channel) { 'write', 'cannot write to IPC channel.'); this.emit('error', er); + } else if (handle && !this._handleQueue) { + this._handleQueue = []; } if (obj && obj.postSend) {