diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 28866d2f2ae668..d2856df489185f 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -455,10 +455,14 @@ function setupChannel(target, channel) { var decoder = new StringDecoder('utf8'); var jsonBuffer = ''; + var pendingHandle = null; channel.buffering = false; channel.onread = function(nread, pool, recvHandle) { // TODO(bnoordhuis) Check that nread > 0. if (pool) { + if (recvHandle) + pendingHandle = recvHandle; + // Linebreak is used as a message end sign var chunks = decoder.write(pool).split('\n'); var numCompleteChunks = chunks.length - 1; @@ -478,10 +482,12 @@ function setupChannel(target, channel) { // read because SCM_RIGHTS messages don't get coalesced. Make sure // that we deliver the handle with the right message however. if (isInternal(message)) { - if (message.cmd === 'NODE_HANDLE') - handleMessage(message, recvHandle, true); - else + if (message.cmd === 'NODE_HANDLE') { + handleMessage(message, pendingHandle, true); + pendingHandle = null; + } else { handleMessage(message, undefined, true); + } } else { handleMessage(message, undefined, false); } diff --git a/test/parallel/test-cluster-send-handle-large-payload.js b/test/parallel/test-cluster-send-handle-large-payload.js new file mode 100644 index 00000000000000..ba529593e28247 --- /dev/null +++ b/test/parallel/test-cluster-send-handle-large-payload.js @@ -0,0 +1,40 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const cluster = require('cluster'); +const net = require('net'); + +const payload = 'a'.repeat(800004); + +if (cluster.isMaster) { + const server = net.createServer(); + + server.on('connection', common.mustCall((socket) => socket.unref())); + + const worker = cluster.fork(); + worker.on('message', common.mustCall(({ payload: received }, handle) => { + assert.strictEqual(payload, received); + assert(handle instanceof net.Socket); + server.close(); + handle.destroy(); + })); + + server.listen(0, common.mustCall(() => { + const port = server.address().port; + const socket = new net.Socket(); + socket.connect(port, (err) => { + assert.ifError(err); + worker.send({ payload }, socket); + }); + })); +} else { + process.on('message', common.mustCall(({ payload: received }, handle) => { + assert.strictEqual(payload, received); + assert(handle instanceof net.Socket); + process.send({ payload }, handle); + + // Prepare for a clean exit. + process.channel.unref(); + handle.unref(); + })); +}