net: multiple listen() events fail silently
Problem: It's possible to run listen() on a net.Server that's already listening to a port. The result is silent failure, with the side effect of changing the connectionKey and or pipeName. Solution: throw an error if listen method called more than once. close() method should be called between listen() method calls. Refs: https://github.com/nodejs/node/pull/8294 Fixes: https://github.com/nodejs/node/issues/6190 Fixes: https://github.com/nodejs/node/issues/11685 PR-URL: https://github.com/nodejs/node/pull/13149 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
484bfa2e37
commit
b24e269a48
@ -809,8 +809,9 @@ This function is asynchronous. `callback` will be added as a listener for the
|
|||||||
|
|
||||||
Returns `server`.
|
Returns `server`.
|
||||||
|
|
||||||
*Note*: The `server.listen()` method may be called multiple times. Each
|
*Note*: The `server.listen()` method can be called again if and only if there was an error
|
||||||
subsequent call will *re-open* the server using the provided options.
|
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])
|
### server.listen(path[, callback])
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
@ -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
|
This function is asynchronous. `callback` will be added as a listener for the
|
||||||
[`'listening'`][] event. See also [`net.Server.listen(path)`][].
|
[`'listening'`][] event. See also [`net.Server.listen(path)`][].
|
||||||
|
|
||||||
*Note*: The `server.listen()` method may be called multiple times. Each
|
*Note*: The `server.listen()` method can be called again if and only if there was an error
|
||||||
subsequent call will *re-open* the server using the provided options.
|
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])
|
### server.listen([port][, hostname][, backlog][, callback])
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
@ -861,8 +863,9 @@ parameter is 511 (not 512).
|
|||||||
This function is asynchronous. `callback` will be added as a listener for the
|
This function is asynchronous. `callback` will be added as a listener for the
|
||||||
[`'listening'`][] event. See also [`net.Server.listen(port)`][].
|
[`'listening'`][] event. See also [`net.Server.listen(port)`][].
|
||||||
|
|
||||||
*Note*: The `server.listen()` method may be called multiple times. Each
|
*Note*: The `server.listen()` method can be called again if and only if there was an error
|
||||||
subsequent call will *re-open* the server using the provided options.
|
during the first `server.listen()` call or `server.close()` has been called.
|
||||||
|
Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
|
||||||
|
|
||||||
### server.listening
|
### server.listening
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
|
@ -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
|
* All [`net.Socket`][] are set to `SO_REUSEADDR` (See [socket(7)][] for
|
||||||
details).
|
details).
|
||||||
|
* The `server.listen()` method can be called again if and only if there was an error
|
||||||
* The `server.listen()` method may be called multiple times. Each
|
during the first `server.listen()` call or `server.close()` has been called.
|
||||||
subsequent call will *re-open* the server using the provided options.
|
Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
|
||||||
|
|
||||||
One of the most common errors raised when listening is `EADDRINUSE`.
|
One of the most common errors raised when listening is `EADDRINUSE`.
|
||||||
This happens when another server is already listening on the requested
|
This happens when another server is already listening on the requested
|
||||||
|
@ -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_NO_LONGER_SUPPORTED', '%s is no longer supported');
|
||||||
E('ERR_OUTOFMEMORY', 'Out of memory');
|
E('ERR_OUTOFMEMORY', 'Out of memory');
|
||||||
E('ERR_PARSE_HISTORY_DATA', 'Could not parse history data in %s');
|
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_ALREADY_BOUND', 'Socket is already bound');
|
||||||
E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536');
|
E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536');
|
||||||
E('ERR_SOCKET_BAD_TYPE',
|
E('ERR_SOCKET_BAD_TYPE',
|
||||||
|
@ -1423,6 +1423,10 @@ Server.prototype.listen = function(...args) {
|
|||||||
var options = normalized[0];
|
var options = normalized[0];
|
||||||
var cb = normalized[1];
|
var cb = normalized[1];
|
||||||
|
|
||||||
|
if (this._handle) {
|
||||||
|
throw new errors.Error('ERR_SERVER_ALREADY_LISTEN');
|
||||||
|
}
|
||||||
|
|
||||||
var hasCallback = (cb !== null);
|
var hasCallback = (cb !== null);
|
||||||
if (hasCallback) {
|
if (hasCallback) {
|
||||||
this.once('listening', cb);
|
this.once('listening', cb);
|
||||||
|
51
test/parallel/test-net-server-call-listen-multiple-times.js
Normal file
51
test/parallel/test-net-server-call-listen-multiple-times.js
Normal file
@ -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()))
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user