Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: multiple listen() events fail silently #13149

Closed
wants to merge 1 commit into from
Closed
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
15 changes: 9 additions & 6 deletions doc/api/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -809,8 +809,9 @@ This function is asynchronous. `callback` will be added as a listener for the

Returns `server`.

*Note*: The `server.listen()` method may be called multiple times. Each
subsequent call will *re-open* the server using the provided options.
*Note*: The `server.listen()` method can be called again if and only if there was an error
during the first `server.listen()` call or `server.close()` has been called.
Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.

### server.listen(path[, callback])
<!-- YAML
Expand All @@ -825,8 +826,9 @@ Start a UNIX socket server listening for connections on the given `path`.
This function is asynchronous. `callback` will be added as a listener for the
[`'listening'`][] event. See also [`net.Server.listen(path)`][].

*Note*: The `server.listen()` method may be called multiple times. Each
subsequent call will *re-open* the server using the provided options.
*Note*: The `server.listen()` method can be called again if and only if there was an error
during the first `server.listen()` call or `server.close()` has been called.
Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.

### server.listen([port][, hostname][, backlog][, callback])
<!-- YAML
Expand Down Expand Up @@ -861,8 +863,9 @@ parameter is 511 (not 512).
This function is asynchronous. `callback` will be added as a listener for the
[`'listening'`][] event. See also [`net.Server.listen(port)`][].

*Note*: The `server.listen()` method may be called multiple times. Each
subsequent call will *re-open* the server using the provided options.
*Note*: The `server.listen()` method can be called again if and only if there was an error
during the first `server.listen()` call or `server.close()` has been called.
Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.

### server.listening
<!-- YAML
Expand Down
6 changes: 3 additions & 3 deletions doc/api/net.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ on Linux. The default value of this parameter is 511 (not 512).

* All [`net.Socket`][] are set to `SO_REUSEADDR` (See [socket(7)][] for
details).

* The `server.listen()` method may be called multiple times. Each
subsequent call will *re-open* the server using the provided options.
* The `server.listen()` method can be called again if and only if there was an error
during the first `server.listen()` call or `server.close()` has been called.
Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.

One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ E('ERR_NO_ICU', '%s is not supported on Node.js compiled without ICU');
E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported');
E('ERR_OUTOFMEMORY', 'Out of memory');
E('ERR_PARSE_HISTORY_DATA', 'Could not parse history data in %s');
E('ERR_SERVER_ALREADY_LISTEN',
'Listen method has been called more than once without closing.');
E('ERR_SOCKET_ALREADY_BOUND', 'Socket is already bound');
E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536');
E('ERR_SOCKET_BAD_TYPE',
Expand Down
4 changes: 4 additions & 0 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,10 @@ Server.prototype.listen = function(...args) {
var options = normalized[0];
var cb = normalized[1];

if (this._handle) {
throw new errors.Error('ERR_SERVER_ALREADY_LISTEN');
}

var hasCallback = (cb !== null);
if (hasCallback) {
this.once('listening', cb);
Expand Down
51 changes: 51 additions & 0 deletions test/parallel/test-net-server-call-listen-multiple-times.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const net = require('net');

// First test. Check that after error event you can listen right away.
{
const dummyServer = net.Server();
const server = net.Server();

// Run some server in order to simulate EADDRINUSE error.
dummyServer.listen(common.mustCall(() => {
// Try to listen used port.
server.listen(dummyServer.address().port);
}));

server.on('error', common.mustCall((e) => {
assert.doesNotThrow(
() => server.listen(common.mustCall(() => {
dummyServer.close();
server.close();
}))
);
}));
}

// Second test. Check that second listen call throws an error.
{
const server = net.Server();

server.listen(common.mustCall(() => server.close()));

common.expectsError(() => server.listen(), {
code: 'ERR_SERVER_ALREADY_LISTEN',
type: Error
});
}

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

server.listen(common.mustCall(() => {
server.close();
assert.doesNotThrow(
() => server.listen(common.mustCall(() => server.close()))
);
}));
}