diff --git a/lib/net.js b/lib/net.js index a51981dda47d45..82205e4352983c 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1970,7 +1970,11 @@ function listenInCluster(server, address, port, addressType, const ex = new ExceptionWithHostPort(err, 'bind', address, port); return server.emit('error', ex); } - + // If there was a handle, just close it to avoid fd leak + // but it doesn't look like that's going to happen right now + if (server._handle) { + server._handle.close(); + } // Reuse primary's server handle server._handle = handle; // _listen2 sets up the listened handle, it is still named like this @@ -1999,6 +2003,8 @@ Server.prototype.listen = function(...args) { options = options._handle || options.handle || options; const flags = getFlags(options.ipv6Only); + // Refresh the id to make the previous call invalid + this._listeningId++; // (handle[, backlog][, cb]) where handle is an object with a handle if (options instanceof TCP) { this._handle = options; diff --git a/test/parallel/test-net-listen-twice.js b/test/parallel/test-net-listen-twice.js new file mode 100644 index 00000000000000..f3e3f1475b54b3 --- /dev/null +++ b/test/parallel/test-net-listen-twice.js @@ -0,0 +1,38 @@ +'use strict'; +const common = require('../common'); +const net = require('net'); +const cluster = require('cluster'); +const assert = require('assert'); + +if (cluster.isPrimary) { + const worker = cluster.fork(); + worker.on('exit', common.mustCall((code) => { + assert.ok(code === 0); + })); +} else { + const server = net.createServer(); + server.listen(); + try { + // Currently, we can call `listen` twice in cluster worker, + // if we can not call `listen` twice in the futrue, + // just skip this test. + server.listen(); + } catch (e) { + console.error(e); + process.exit(0); + } + let i = 0; + process.on('internalMessage', (msg) => { + if (msg.cmd === 'NODE_CLUSTER') { + if (++i === 2) { + setImmediate(() => { + server.close(() => { + process.disconnect(); + }); + }); + } + } + }); + // Must only call once + server.on('listening', common.mustCall()); +}