diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index d1596406cf9d53..8c1abc5f746fc8 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -449,6 +449,7 @@ function setupChannel(target, channel) { target.disconnect(); channel.onread = nop; channel.close(); + target._channel = null; maybeClose(target); } }; diff --git a/test/parallel/test-child-process-fork-regr-gh-2847.js b/test/parallel/test-child-process-fork-regr-gh-2847.js new file mode 100644 index 00000000000000..07ef6415a3c3e1 --- /dev/null +++ b/test/parallel/test-child-process-fork-regr-gh-2847.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const cluster = require('cluster'); +const net = require('net'); +const util = require('util'); + +if (!cluster.isMaster) { + // Exit on first received handle to leave the queue non-empty in master + process.on('message', function() { + process.exit(1); + }); + return; +} + +var server = net.createServer(function(s) { + setTimeout(function() { + s.destroy(); + }, 100); +}).listen(common.PORT, function() { + var worker = cluster.fork(); + + function send(callback) { + var s = net.connect(common.PORT, function() { + worker.send({}, s, callback); + }); + } + + worker.process.once('close', common.mustCall(function() { + // Otherwise the crash on `_channel.fd` access may happen + assert(worker.process._channel === null); + server.close(); + })); + + // Queue up several handles, to make `process.disconnect()` wait + for (var i = 0; i < 100; i++) + send(); +});