Permalink
Browse files

child_process: acknowledge sent handles

fix race-condition when multiple handles are sent and SCM_RIGHTS
messages are gets merged by OS by avoiding sending multiple handles at
once!

fix #4885
  • Loading branch information...
1 parent e5b90a1 commit f6d09e5b1c9eb6de6521fe4ee0b664991b28826b @indutny committed Apr 1, 2013
Showing with 29 additions and 0 deletions.
  1. +29 −0 lib/child_process.js
View
@@ -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) {

0 comments on commit f6d09e5

Please sign in to comment.