python-trio / python-trio/trio
How to handle automatic port selection in open_tcp_listeners when we have multiple sockets?
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 7.3k
- Forks
- 431
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 6
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the open_tcp_listeners(0) entry point and compare its behavior with the referenced Tornado implementation. Work out and agree on a policy for shared ephemeral-port selection across IPv4 and IPv6, including bind races and retry conditions; done means the behavior and failure cases are defined and covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100