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
_getaddrinfo with family AF_UNSPEC in resolver_ares.py always queries both ipv4 and ipv6 #1012
Comments
My man page for
I don't see anything in either text that definitively says only one or the other will ever be queried, or indeed spells out behaviour when nameservers are/not reachable. There is a list of differences in how the c-ares resolver works compared to the native resolver. I would consider a PR that summarizes this into a bullet point for that list. The entry about "ipv6 and ipv4 may be considered and returned in different orders" comes close. Handling of UPDATE: This c-ares bug is relevant and explains why gevent does what it does. |
Thank you for the detailed report and analysis, by the way. |
Yes, c-ares/c-ares#70 is a reason why feeding
With fix feeding
The fix applied here is diff --git a/src/gevent/resolver_ares.py b/src/gevent/resolver_ares.py
index 196e4c47..cf08af46 100644
--- a/src/gevent/resolver_ares.py
+++ b/src/gevent/resolver_ares.py
@@ -197,9 +197,8 @@ class Resolver(object):
ares = self.ares
if family == AF_UNSPEC:
- ares_values = Values(self.hub, 2)
- ares.gethostbyname(ares_values, host, AF_INET)
- ares.gethostbyname(ares_values, host, AF_INET6)
+ ares_values = Values(self.hub, 1)
+ ares.gethostbyname(ares_values, host, AF_UNSPEC)
elif family == AF_INET:
ares_values = Values(self.hub, 1)
ares.gethostbyname(ares_values, host, AF_INET) On the other hand, it fixes issues described above, removing problems from |
I view the current gevent behaviour as a reasonable compromise until the c-ares issue is fixed. Once it is, we can update and adapt. |
FWIW, the new-in-1.3a2 |
I've danced around |
Description:
When
ares
resolver is used,gevent.socket.getaddrinfo
is implemented bygevent.resolver_ares.Resolver.getaddrinfo
which just callsgevent.resolver_ares.Resolver._getaddrinfo
- a wrapper aroundares
. When address family parameter is set toAF_UNSPEC
, it will useares
to make bothipv4
andipv6
query - and wait for both results. The relevant code is (https://github.com/gevent/gevent/blob/27db87a/src/gevent/resolver_ares.py#L199):This is not exactly how libc's (and, hence, built-in python's)
getaddrinfo
works and has problems whenhost
is a domain name defined in/etc/hosts
for only one ofipv4
oripv6
, but not both. In this case standardgetaddrinfo
will immediately return info about the address it found without querying DNS server through network. This is consistent withman
page forgetaddrinfo
, which saysAF_UNSPEC
requests adresses for any family, (as far as I understand, it means not nesessarily both):The code in
resolver_ares.py
, on the contrary, will forceares
to resolve for both families, causing it to make DNS requests through network for the address family for which hostname is not defined in/etc/hosts
.This has several problems:
8.8.8.8
) and some extra delay.A situation when a hostname is configured only for
ipv4
is rather common - for example, a fresh ubuntu install will add a record for its hostname foripv4
, but notipv6
. Situation when a program feeds it's hostname togetaddrinfo
is also not uncommon - it happens when it callsgetfqdn
with no arguments or with argument0.0.0.0
, for example it can happen when gevent'sWSGIServer
starts: https://github.com/gevent/gevent/blob/master/src/gevent/pywsgi.py#L1485Reproducing
I used the following script for testing:
I tested the issue on two test stands - a VM and a docker container. Here is how it looks on a VM (Ubuntu 17.04):
$ cat /etc/resolv.conf nameserver 8.8.8.8 $ cat /etc/hosts 127.0.0.1 localhost 127.0.1.1 ares-dns-test # The following lines are desirable for IPv6 capable hosts ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters
Running test script without
ares
(regular resolver is used):Using
ares
:Wireshark shows:

Now, if we cut out network (for docker, bringing down
docker0
interface of host will give the same effect):The same happens with
getfqdn
andWSGIServer
:The text was updated successfully, but these errors were encountered: