From c7a7253c879e98672924d21ccce69349e7b076f0 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 It is possible that the internal handleMessage() 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/5153 Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis --- lib/child_process.js | 3 ++ test/simple/test-cluster-disconnect-race.js | 34 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 test/simple/test-cluster-disconnect-race.js diff --git a/lib/child_process.js b/lib/child_process.js index 9bb64e64b66cf3..0c360e082f4269 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -313,6 +313,9 @@ function getSocketList(type, slave, key) { var INTERNAL_PREFIX = 'NODE_'; function handleMessage(target, message, handle) { + if (!target._channel) + return; + var eventName = 'message'; if (!util.isNull(message) && util.isObject(message) && diff --git a/test/simple/test-cluster-disconnect-race.js b/test/simple/test-cluster-disconnect-race.js new file mode 100644 index 00000000000000..fdf53b967c92bc --- /dev/null +++ b/test/simple/test-cluster-disconnect-race.js @@ -0,0 +1,34 @@ +'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 + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var 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)); + }, 2)); + + cluster.on('exit', function(worker, code) { + assert.strictEqual(code, 0, 'worker exited with error'); + }); + + return; +} + +var server = net.createServer(); + +server.listen(common.PORT, function retry() { + process.send('listening'); + process.send('listening'); +});