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 #6190

Closed
trevnorris opened this issue Apr 13, 2016 · 13 comments
Closed

net: multiple listen() events fail silently #6190

trevnorris opened this issue Apr 13, 2016 · 13 comments
Labels
net Issues and PRs related to the net subsystem.

Comments

@trevnorris
Copy link
Contributor

  • Version: >= v4.x
  • Platform: All
  • Subsystem: net

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.

More expected behavior would be to emit an error on the server's 'error' event handler.

Example test:

const assert = require('assert');
const net = require('net');
const server = net.createServer();
server.on('error', () => {
  process._rawDebug('server had an error');
});
server.listen(8080).listen(8081);
process.on('exit', () => {
  assert.equal(server.address().port, 8080);
  const key = server._connectionKey;
  assert.equal(key.substr(key.lastIndexOf(':')), ':8080');
});
@trevnorris trevnorris added net Issues and PRs related to the net subsystem. good first issue Issues that are suitable for first-time contributors. labels Apr 13, 2016
@geppy
Copy link

geppy commented Apr 14, 2016

I'd like to work this one. Reading through the CONTRIBUTING doc now.

@trevnorris
Copy link
Contributor Author

@geppy Awesome. If you get a PR up, even if it's WIP, cc me and I'll be happy to help you out.

@bnoordhuis
Copy link
Member

More expected behavior would be to emit an error on the server's 'error' event handler.

I think it makes more sense to throw an exception. Calling listen() repeatedly likely means there's a logic error in the application.

@trevnorris
Copy link
Contributor Author

trevnorris commented Apr 15, 2016

@bnoordhuis there's a potential timing issue. currently if you call .listen() twice, and each time pass a hostname, it will send out a dns request. which doesn't fill _handle until later. allowing the instance to think that listen() hasn't yet been called.

i think that'd be as simple as storing a _listenHasBeenCalled flag on the instance so we can throw immediately, but haven't looked at that in much detail.

@justsml
Copy link

justsml commented Apr 15, 2016

Hi @trevnorris - I did a minimal implementation.

I have a few questions though:

  1. Is it important for the server._connectionKey or server.address() to (always) be set before the error throws?
  2. Should I move the throw/error closer to the DNS lookup?
  3. Should property Server.listening only check this._handle - or should it also test this._listenHasBeenCalled

@justsml
Copy link

justsml commented Apr 18, 2016

Hey @geppy - I just re-read this after the weekend & wanted to say I didn't mean to step on your toes!

This would be my first contribution into the core nodejs project. (I've only helped on the website side of things ... so far.)

I started on this after seeing @trevnorris 's tweet - but stalled after you 'called it'.
When I saw Trevors latest comment about _listenHasBeenCalled I jumped on it as I (essentially) already implemented such a pattern.

That said, please don't let me stop you from doing a PR - the more the merrier. 💯

Hope everyone had a good weekend!!!

@geppy
Copy link

geppy commented Apr 18, 2016

@justsml Okay, thanks! I'll go ahead and file my PR when I get home.

@saghul
Copy link
Member

saghul commented Apr 20, 2016

I guess the case in which someone calls listen more than once to change the backlog is too weird to consider, right?

@bnoordhuis
Copy link
Member

I'm undecided. I've been programming UNIX services for twenty years now and I've never had to adjust the backlog dynamically; it seems like a very obscure feature. Perhaps we can support it if it's almost free to do so implementation/maintenance-wise, but otherwise I wouldn't bother.

I am admittedly responsible for making it adjustable in libuv but my rationale at the time can be summarized as "why not?".

@saghul
Copy link
Member

saghul commented Apr 21, 2016

@bnoordhuis I defer to your good judgement and experience here, I just thought I'd bring it up just in case :-)

@trevnorris
Copy link
Contributor Author

@bnoordhuis My main concern here is that calling .listen() twice overwrites the ._handle. Thus preventing the user a way to close the server, unless they use this from a server's event. Here's an example of strange behavior:

const server = require('net').createServer(function(c) {
  console.error(this.address());
}).listen(8080, 'localhost');

server.listen(8081);

Then run nc -v localhost 8080 you'll see the connection failed, and the connection handler is placed on port 8081. But if you change it to .listen(8080) you'll see that you can successfully connect, and port 8081 is refused.

Basically, I'd like to see consistency more than anything and figured the easiest way to do this was remove the ability to call .listen() multiple times.

@eduardbme
Copy link
Contributor

eduardbme commented Sep 5, 2016

Hi there.
I am new to contribution to nodejs and decided to start with 'good first contribution' label.
It looks like you discussed this problem, but I've compiled current master branch and the problem still exists and the problem still open..
So I wrote simple solution with _listenHasBeenCalled variable and I am wondering whether community still interesting in it.
Many thanks.

@Trott
Copy link
Member

Trott commented Jul 10, 2017

Removing good first contribution since we have a PR open for this: #13149

@Trott Trott removed the good first issue Issues that are suitable for first-time contributors. label Jul 10, 2017
eduardbme added a commit to eduardbme/node that referenced this issue Sep 2, 2017
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: nodejs#8294
Fixes: nodejs#6190
Fixes: nodejs#11685
addaleax pushed a commit to addaleax/ayo that referenced this issue Sep 5, 2017
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: nodejs/node#8294
Fixes: nodejs/node#6190
Fixes: nodejs/node#11685
PR-URL: nodejs/node#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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
net Issues and PRs related to the net subsystem.
Projects
None yet
7 participants