You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
loop.create_server does not detect if the interface is IPv6 enabled #75128
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2017-07-17.10:04:34.577>labels= ['type-bug', '3.7', 'expert-asyncio']
title='loop.create_server does not detect if the interface is IPv6 enabled'updated_at=<Date2018-10-19.21:14:34.454>user='https://github.com/cecton'
The IPv6 detection in asyncio.base_events.create_server only detect if IPv6 is available instead of checking if the interface can actually support it.
I noticed that by using Python in a Docker container (example code to reproduce in attachment):
docker run -it --rm -v /tmp/test_ipv6.py:/src/test_ipv6.py python:3.6 python /src/test_ipv6.py
Will result in:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/asyncio/base_events.py", line 1043, in create_server
sock.bind(sa)
OSError: [Errno 99] Cannot assign requested address
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/src/test_ipv6.py", line 11, in <module>
server = loop.run_until_complete(server_creation)
File "/usr/local/lib/python3.6/asyncio/base_events.py", line 466, in run_until_completereturn future.result()
File "/usr/local/lib/python3.6/asyncio/base_events.py", line 1047, in create_server% (sa, err.strerror.lower()))
OSError: [Errno 99] error while attempting to bind on address ('::1', 27015, 0, 0): cannot assign requested address
By default Docker containers have only IPv4 enabled:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
I believe this detection mechanism should rely on the interface requested. I found this on the web for Python 2 that manage to get the info per interface: https://pastebin.com/VEnhF1Ht but it's using an external library.
However if you change the hostname to 127.0.0.1 it works normally.
Cécile, thank you. The reason the message is still displayed is that I turned the error into a warning (in other words, it is expected).
asottile commented on Feb 9, 2018
asottilemannequin
Mannequin
More actions
Seeing this as well when running the cpython test suite in docker:
$ ./python -m test.test_asyncio
...
[18 similar traces omitted]
======================================================================
ERROR: test_sock_sendfile_zero_size (test.test_asyncio.test_unix_events.SelectorEventLoopUnixSockSendfileTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/code/Lib/test/test_asyncio/test_unix_events.py", line 559, in test_sock_sendfile_zero_size
sock, proto = self.prepare()
File "/code/Lib/test/test_asyncio/test_unix_events.py", line 483, in prepare
lambda: proto, support.HOST, port))
File "/code/Lib/test/test_asyncio/test_unix_events.py", line 476, in run_loop
return self.loop.run_until_complete(coro)
File "/code/Lib/asyncio/base_events.py", line 566, in run_until_complete
return future.result()
File "/code/Lib/asyncio/base_events.py", line 1346, in create_server
% (sa, err.strerror.lower())) from None
OSError: [Errno 99] error while attempting to bind on address ('::1', 39527, 0, 0): cannot assign requested address
----------------------------------------------------------------------
I'm going to try and write a patch to skip these tests (there's already a helper)
asottile commented on Feb 9, 2018
asottilemannequin
Mannequin
More actions
Actually, my issue seems to be something more strange.
The host being passed in is localhost which resolves to:
# Disable IPv4/IPv6 dual stack support (enabled by
# default on Linux) which makes a single socket
# listen on both address families.
ifaf==AF_INET6andhasattr(socket, 'IPPROTO_IPV6'):
sock.setsockopt(socket.IPPROTO_IPV6,
socket.IPV6_V6ONLY,
True)
despite my host not actually having an ipv6 network hooked up.
Which should be fine; create_server enumerates all addresses and tries to connect to each one. IPV6_V6ONLY is only applied to one socket for one IPv6 address. I think Antoine's patch is OK.
Thank you for your patch Antoine. I am surprised that it was not merged at its time. It fixes a constant failure on some buildbots. Buildbot failure could perhaps be fixed by changing the configuration (I think that I encountered such errors on different buildbots in the past), but it is better to fix it in the core.
Activity
cecton commentedon Jul 17, 2017
The IPv6 detection in asyncio.base_events.create_server only detect if IPv6 is available instead of checking if the interface can actually support it.
I noticed that by using Python in a Docker container (example code to reproduce in attachment):
docker run -it --rm -v /tmp/test_ipv6.py:/src/test_ipv6.py python:3.6 python /src/test_ipv6.py
Will result in:
By default Docker containers have only IPv4 enabled:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
I believe this detection mechanism should rely on the interface requested. I found this on the web for Python 2 that manage to get the info per interface: https://pastebin.com/VEnhF1Ht but it's using an external library.
However if you change the hostname to 127.0.0.1 it works normally.
pitrou commentedon Jul 19, 2017
Better than trying to detect IPv6 compatibility beforehand would probably to recognize the error and simply ignore it.
Note: errno 99 is EADDRNOTAVAIL.
Something like this could work (untested):
1st1 commentedon Jul 19, 2017
+1
pitrou commentedon Jul 20, 2017
Cécile, could you try the following patch? I have no easy way to test here.
cecton commentedon Jul 20, 2017
Sure! It seems to work, the process returns an exit code of 0 and I see no traceback but the message is still displayed in the terminal.
(Also I did something weird because your patch applies on branch master and I ran it with Python 3.6... I suppose it shouldn't be a problem)
[0] [11:54:13] /tmp > d run -it --rm -v /tmp:/tmp:ro -v ~/repos/cpython/Lib/asyncio:/usr/local/lib/python3.6/asyncio:ro python:3.6 python /tmp/test_ipv6.py error while attempting to bind on address ('::1', 27015, 0, 0): cannot assign requested address [0] [11:54:19] /tmp > d run -it --rm -v /tmp:/tmp:ro python:3.6 python /tmp/test_ipv6.py Traceback (most recent call last): File "/usr/local/lib/python3.6/asyncio/base_events.py", line 1043, in create_server sock.bind(sa) OSError: [Errno 99] Cannot assign requested address During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/tmp/test_ipv6.py", line 11, in <module> server = loop.run_until_complete(server_creation) File "/usr/local/lib/python3.6/asyncio/base_events.py", line 466, in run_until_complete return future.result() File "/usr/local/lib/python3.6/asyncio/base_events.py", line 1047, in create_server % (sa, err.strerror.lower())) OSError: [Errno 99] error while attempting to bind on address ('::1', 27015, 0, 0): cannot assign requested address [1] [11:54:52] /tmp >pitrou commentedon Jul 20, 2017
Cécile, thank you. The reason the message is still displayed is that I turned the error into a warning (in other words, it is expected).
asottile commentedon Feb 9, 2018
Seeing this as well when running the cpython test suite in docker:
I'm going to try and write a patch to skip these tests (there's already a helper)
asottile commentedon Feb 9, 2018
Actually, my issue seems to be something more strange.
The host being passed in is
localhostwhich resolves to:asyncio is picking ipv6 because of this code:
cpython/Lib/asyncio/base_events.py
Lines 1334 to 1340 in a445feb
despite my host not actually having an ipv6 network hooked up.
asottile commentedon Feb 9, 2018
Applying this patch makes the tests pass for me, but I don't think the patch is appropriate (just hides the bug):
cecton commentedon Feb 10, 2018
I see that the patch hasn't been applied to master on GitHub. Is there anything else expected from me on this ticket?
1st1 commentedon May 28, 2018
Does anybody wants to make a PR to fix this?
1st1 commentedon May 29, 2018
Which should be fine; create_server enumerates all addresses and tries to connect to each one. IPV6_V6ONLY is only applied to one socket for one IPv6 address. I think Antoine's patch is OK.
pythongh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.c…
gh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.create_…
pythongh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.c…
pythongh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.c…
serhiy-storchaka commentedon Jan 22, 2024
Thank you for your patch Antoine. I am surprised that it was not merged at its time. It fixes a constant failure on some buildbots. Buildbot failure could perhaps be fixed by changing the configuration (I think that I encountered such errors on different buildbots in the past), but it is better to fix it in the core.
[3.12] gh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.…
[3.11] gh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.…
pythongh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.c…
pythongh-75128: Ignore EADDRNOTAVAIL error in asyncio.BaseEventLoop.c…