Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,7 @@ function Server(options, connectionListener) {

this[async_id_symbol] = -1;
this._handle = null;
this._listening = false;
this._usingWorkers = false;
this._workers = [];
this._unref = false;
Expand Down Expand Up @@ -2389,6 +2390,7 @@ Server.prototype[kTransfer] = function() {
};
// Detach so the source server no longer references the handle being moved.
this._handle = null;
this._listening = false;
return {
data,
deserializeInfo: 'net:Server',
Expand All @@ -2412,6 +2414,7 @@ Server.prototype[kDeserialize] = function(data) {
};

function emitErrorNT(self, err) {
self._listening = false;
self.emit('error', err);
}

Expand Down Expand Up @@ -2458,6 +2461,7 @@ function listenInCluster(server, address, port, addressType,

if (err) {
const ex = new ExceptionWithHostPort(err, 'bind', address, port);
server._listening = false;
return server.emit('error', ex);
}
// If there was a handle, just close it to avoid fd leak
Expand All @@ -2479,7 +2483,7 @@ Server.prototype.listen = function(...args) {
let options = normalized[0];
const cb = normalized[1];

if (this._handle) {
if (this._handle || this._listening) {
throw new ERR_SERVER_ALREADY_LISTEN();
}

Expand Down Expand Up @@ -2511,6 +2515,7 @@ Server.prototype.listen = function(...args) {
this._pipeName = boundPath;
}
this[async_id_symbol] = this._handle.getAsyncId();
this._listening = true;
this._listeningId++;
listenInCluster(this, null, -1, -1, backlogFromArgs, undefined, true);
return this;
Expand All @@ -2523,12 +2528,14 @@ Server.prototype.listen = function(...args) {
if (options instanceof TCP) {
this._handle = options;
this[async_id_symbol] = this._handle.getAsyncId();
this._listening = true;
listenInCluster(this, null, -1, -1, backlogFromArgs, undefined, true);
return this;
}
addServerAbortSignalOption(this, options);
// (handle[, backlog][, cb]) where handle is an object with a fd
if (typeof options.fd === 'number' && options.fd >= 0) {
this._listening = true;
listenInCluster(this, null, null, null, backlogFromArgs, options.fd);
return this;
}
Expand All @@ -2553,6 +2560,7 @@ Server.prototype.listen = function(...args) {
options.exclusive = true;
}
// start TCP server listening on host:port
this._listening = true;
if (options.host) {
lookupAndListen(this, options.port | 0, options.host, backlog,
options.exclusive, flags);
Expand All @@ -2575,6 +2583,7 @@ Server.prototype.listen = function(...args) {
}
const pipeName = this._pipeName = options.path;
backlog = options.backlog || backlogFromArgs;
this._listening = true;
listenInCluster(this,
pipeName,
-1,
Expand Down Expand Up @@ -2604,6 +2613,7 @@ Server.prototype.listen = function(...args) {
if (err) {
this._handle.close();
this._handle = null;
this._listening = false;
throw new ErrnoException(err, 'uv_pipe_chmod');
}
}
Expand Down Expand Up @@ -2657,6 +2667,7 @@ function lookupAndListen(self, port, address, backlog,
return;
}
if (err) {
self._listening = false;
self.emit('error', err);
} else {
const validAddress = filterOnlyValidAddress(addresses);
Expand Down Expand Up @@ -2811,6 +2822,7 @@ Server.prototype.getConnections = function(cb) {


Server.prototype.close = function(cb) {
this._listening = false;
this._listeningId++;
if (typeof cb === 'function') {
if (!this._handle) {
Expand Down
30 changes: 7 additions & 23 deletions test/parallel/test-net-listen-twice.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,12 @@ if (cluster.isPrimary) {
}));
} 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 future,
// just skip this test.
server.listen();
} catch (e) {
console.error(e);
return;
}
let i = 0;
process.on('internalMessage', (msg) => {
if (msg.cmd === 'NODE_CLUSTER') {
if (++i === 2) {
setImmediate(() => {
server.close(() => {
process.disconnect();
});
});
}
}
server.listen(common.mustCall(() => {
server.close(() => process.disconnect());
}));

assert.throws(() => server.listen(), {
code: 'ERR_SERVER_ALREADY_LISTEN',
name: 'Error'
});
// Must only call once
server.on('listening', common.mustCall());
}
16 changes: 15 additions & 1 deletion test/parallel/test-net-server-call-listen-multiple-times.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,21 @@ const net = require('net');
});
}

// Third test.
// Third test. Check that a second listen call throws while the first is pending.
{
const server = net.Server();

server.listen(0, '127.0.0.1');

assert.throws(() => server.listen(), {
code: 'ERR_SERVER_ALREADY_LISTEN',
name: 'Error'
});

server.close();
}

// Fourth test.
// Check that after the close call you can run listen method just fine.
{
const server = net.Server();
Expand Down
Loading