diff --git a/lib/net.js b/lib/net.js index cf8be1601c30d7..c3ee2f4a920a06 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1773,6 +1773,7 @@ function Server(options, connectionListener) { this._usingWorkers = false; this._workers = []; this._unref = false; + this._listeningId = 1; this.allowHalfOpen = options.allowHalfOpen || false; this.pauseOnConnect = !!options.pauseOnConnect; @@ -1954,10 +1955,14 @@ function listenInCluster(server, address, port, addressType, backlog, ...options, }; + const listeningId = server._listeningId; // Get the primary's server handle, and listen on it cluster._getServer(server, serverQuery, listenOnPrimaryHandle); - function listenOnPrimaryHandle(err, handle) { + if (listeningId !== server._listeningId) { + handle.close(); + return; + } err = checkBindError(err, port, handle); if (err) { @@ -2089,9 +2094,14 @@ Server.prototype.listen = function(...args) { throw new ERR_INVALID_ARG_VALUE('options', options); }; -function lookupAndListen(self, port, address, backlog, exclusive, flags) { +function lookupAndListen(self, port, address, backlog, + exclusive, flags) { if (dns === undefined) dns = require('dns'); + const listeningId = self._listeningId; dns.lookup(address, function doListen(err, ip, addressType) { + if (listeningId !== self._listeningId) { + return; + } if (err) { self.emit('error', err); } else { @@ -2237,6 +2247,7 @@ Server.prototype.getConnections = function(cb) { Server.prototype.close = function(cb) { + this._listeningId++; if (typeof cb === 'function') { if (!this._handle) { this.once('close', function close() { diff --git a/test/parallel/test-net-server-close-before-calling-lookup-callback.js b/test/parallel/test-net-server-close-before-calling-lookup-callback.js new file mode 100644 index 00000000000000..58cfc5504c04fa --- /dev/null +++ b/test/parallel/test-net-server-close-before-calling-lookup-callback.js @@ -0,0 +1,7 @@ +'use strict'; + +const common = require('../common'); +const net = require('net'); +// Process should exit because it does not create a real TCP server. +// Paas localhost to ensure create TCP handle asynchronously because It causes DNS resolution. +net.createServer().listen(0, 'localhost', common.mustNotCall()).close(); diff --git a/test/parallel/test-net-server-close-before-ipc-response.js b/test/parallel/test-net-server-close-before-ipc-response.js new file mode 100644 index 00000000000000..e85bc96ee6200c --- /dev/null +++ b/test/parallel/test-net-server-close-before-ipc-response.js @@ -0,0 +1,22 @@ +'use strict'; + +const common = require('../common'); +const net = require('net'); +const cluster = require('cluster'); + +// Process should exit +if (cluster.isPrimary) { + cluster.fork(); +} else { + const send = process.send; + process.send = function(message) { + // listenOnPrimaryHandle in net.js should call handle.close() + if (message.act === 'close') { + setImmediate(() => { + process.disconnect(); + }); + } + return send.apply(this, arguments); + }; + net.createServer().listen(0, common.mustNotCall()).close(); +}