This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author jcristharif
Recipients asvetlov, eric.smith, jcristharif, yselivanov
Date 2021-11-03.21:42:00
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1635975720.69.0.87602220848.issue45693@roundup.psfhosted.org>
In-reply-to
Content
> Is tornado the only example or you are aware of other libraries with such behavior?

A quick survey of other language network stacks didn't turn anything up, *But* I also didn't find any implementations (other than asyncio & tornado) that bind multiple sockets with a single api call (as `create_server` does).

I think part of the issue here is that dual IPV6 & IPV4 support is intentionally disabled in asyncio (and tornado), so two sockets are needed (one to support each interface). Other TCP implementations (e.g. both go and rust) don't disable this, so one listener == one socket. This makes comparing API designs across stacks harder - with e.g. Go it's straightforward to listen on a random port on IPV4 & IPV6 with a single TCPListener, since both can be handled by a single socket. Since this is disabled (by default) in asyncio we end up using 2 sockets and run into the issue described above.

Also note that this issue will trigger for any address that resolves to multiple interfaces (not just `host=""`). For example, on osx `localhost` will resolve to `::1` and `127.0.0.1` by default, meaning that the following fairly straightforward asyncio code has a bug in it:

```python
# Start a server on localhost with a random port
server = await loop.create_server(
    EchoServerProtocol,
    host="localhost",
    port=0
)

# Retrieve and log the port
port = server.sockets[0].getsockname()[1]
print(f"listening at tcp://localhost:{port}")
```

As written, this looks correct enough, but on systems where localhost resolves to multiple interfaces this will accidentally listen on multiple ports (instead of one). This can be fixed with some additional logic external to asyncio, but it makes for a much less straightforward asyncio example.
History
Date User Action Args
2021-11-03 21:42:00jcristharifsetrecipients: + jcristharif, eric.smith, asvetlov, yselivanov
2021-11-03 21:42:00jcristharifsetmessageid: <1635975720.69.0.87602220848.issue45693@roundup.psfhosted.org>
2021-11-03 21:42:00jcristhariflinkissue45693 messages
2021-11-03 21:42:00jcristharifcreate