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

How to handle automatic port selection in open_tcp_listeners when we have multiple sockets? #283

Open
njsmith opened this issue Aug 11, 2017 · 0 comments

Comments

@njsmith
Copy link
Member

njsmith commented Aug 11, 2017

it's confusing that open_tcp_listeners(0) by default gives you different ports on ipv4 and ipv6. there aren't great options here though. The only way to ask the kernel for a single port that works on all protocols and interfaces is to make a IPV6ONLY=False socket, bind to ("::", 0), and see what port you get. Actually using such a socket seems too messy to be workable – there's address translation issues in and out, and Linux getaddrinfo acts weird (getaddrinfo("google.com", 80, family=AF_INET6, flags=AI_V4MAPPED | AI_ALL) only returns v4 addresses? wtf that's not what the docs say), and what do you do anyway if they don't want the wildcard address. Which means that once you have the port you have to close it and bind new sockets, and now there's a race condition b/c someone else could steal one, which means you need to retry, but this seems kinda messy. (Plus can we really distinguish reliably between an error that means we should retry and one that means we should bail out?) And what if they want to bind to several v4 addresses, should we then only probe the v4 wildcard? And what if we have a busy server where one interface has run out of ephemeral ports but another hasn't?

it looks like tornado does this, just ignoring the race condition like my original implementation: https://github.com/tornadoweb/tornado/blob/d4094a0c2a7cddc654381c162ee7786d4bf8453b/tornado/netutil.py#L190-L194

I guess it is possible to know that you should retry in the specific case where bind gives EADDRINUSE and you already made sure it was free a moment ago.

I also guess it's very rare to use ephemeral ports on real busy servers? I dunno.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant