From 35e32985caf6e71c7f8c0b4339cd27b7bcd75b08 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 24 Dec 2015 13:00:29 -0800 Subject: [PATCH] child_process: guard against race condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible that the internal hnadleMessage() might try to send to a channel that has been closed. The result can be an AssertionError. Guard against this. Fixes: https://github.com/nodejs/node/issues/4205 PR-URL: https://github.com/nodejs/node/pull/4418 Reviewed-By: Brian White Reviewed-By: Johan Bergström --- lib/internal/child_process.js | 3 ++ test/parallel/test-cluster-disconnect-race.js | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 test/parallel/test-cluster-disconnect-race.js diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 8b2e57eb10ba74..b4365fb8c067f7 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -675,6 +675,9 @@ function setupChannel(target, channel) { const INTERNAL_PREFIX = 'NODE_'; function handleMessage(target, message, handle) { + if (!target._channel) + return; + var eventName = 'message'; if (message !== null && typeof message === 'object' && diff --git a/test/parallel/test-cluster-disconnect-race.js b/test/parallel/test-cluster-disconnect-race.js new file mode 100644 index 00000000000000..40cfd919e3e964 --- /dev/null +++ b/test/parallel/test-cluster-disconnect-race.js @@ -0,0 +1,33 @@ +'use strict'; + +// This code triggers an AssertionError on Linux in Node.js 5.3.0 and earlier. +// Ref: https://github.com/nodejs/node/issues/4205 + +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); +const cluster = require('cluster'); +cluster.schedulingPolicy = cluster.SCHED_NONE; + +if (cluster.isMaster) { + var worker1, worker2; + + worker1 = cluster.fork(); + worker1.on('message', common.mustCall(function() { + worker2 = cluster.fork(); + worker1.disconnect(); + worker2.on('online', common.mustCall(worker2.disconnect)); + })); + + cluster.on('exit', function(worker, code) { + assert.strictEqual(code, 0, 'worker exited with error'); + }); + + return; +} + +var server = net.createServer(); + +server.listen(common.PORT, function() { + process.send('listening'); +});