Commit b6525015 authored by Jason Madden's avatar Jason Madden

Support GEVENT_RESOLVER_SERVERS for configuring dnspython nameservers.

Also allow this for ares, and deprecate the GEVENTARES_SERVERS environment variable.

Fixes #1103.
parent 1c8c7375
......@@ -36,7 +36,10 @@
:func:`gevent.subprocess.run`.
- Add the ``dnspython`` resolver as a lightweight alternative to
c-ares. See :pr:`1088`.
c-ares. See :pr:`1088` and :issue:`1103`.
- The ``GEVENTARES_SERVERS`` environment variable is deprecated in
favor of ``GEVENT_RESOLVER_SERVERS``. See :issue:`1103`.
- Fix calling ``shutdown`` on a closed socket. It was raising
``AttributeError``, now it once again raises the correct
......
......@@ -10,6 +10,7 @@ CYTHON?=cython
export PATH:=$(BUILD_RUNTIMES)/snakepit:$(TOOLS):$(PATH)
export LC_ALL=C.UTF-8
export GEVENT_RESOLVER_NAMESERVERS=8.8.8.8
clean:
......@@ -61,7 +62,7 @@ basictest: test_prelim
alltest: basictest
@${PYTHON} scripts/travis.py fold_start ares "Running c-ares tests"
cd src/greentest && GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 ${PYTHON} testrunner.py --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
cd src/greentest && GEVENT_RESOLVER=ares ${PYTHON} testrunner.py --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
@${PYTHON} scripts/travis.py fold_end ares
@${PYTHON} scripts/travis.py fold_start dnspython "Running dnspython tests"
cd src/greentest && GEVENT_RESOLVER=dnspython ${PYTHON} testrunner.py --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
......
......@@ -447,7 +447,67 @@ class AresServers(AresSettingMixin, Setting):
name = 'ares_servers'
default = None
environment_key = 'GEVENTARES_SERVERS'
desc = """\
A list of strings giving the IP addresses of nameservers for the ares resolver.
In the environment variable, these strings are separated by commas.
.. deprecated:: 1.3a2
Prefer the :attr:`resolver_nameservers` setting. If both are set,
the results are not defined.
"""
# Generic nameservers, works for dnspython and ares.
class ResolverNameservers(AresSettingMixin, Setting):
document = True
name = 'resolver_nameservers'
default = None
environment_key = 'GEVENT_RESOLVER_NAMESERVERS'
desc = """\
A list of strings giving the IP addresses of nameservers for the (non-system) resolver.
In the environment variable, these strings are separated by commas.
.. rubric:: Resolver Behaviour
* blocking
Ignored
* Threaded
Ignored
* dnspython
If this setting is not given, the dnspython resolver will
load nameservers to use from ``/etc/resolv.conf``
or the Windows registry. This setting replaces any nameservers read
from those means. Note that the file and registry are still read
for other settings.
.. caution:: dnspython does not validate the members of the list.
An improper address (such as a hostname instead of IP) has
undefined results, including hanging the process.
* ares
Similar to dnspython, but with more platform and compile-time
options. ares validates that the members of the list are valid
addresses.
"""
# Normal string-to-list rules. But still validate_anything.
_convert = Setting._convert
# TODO: In the future, support reading a resolv.conf file
# *other* than /etc/resolv.conf, and do that both on Windows
# and other platforms. Also offer the option to disable the system
# configuration entirely.
@property
def kwarg_name(self):
return 'servers'
config = Config()
......
......@@ -9,6 +9,8 @@ import sys
from cpython.ref cimport Py_INCREF
from cpython.ref cimport Py_DECREF
from cpython.mem cimport PyMem_Malloc
from cpython.mem cimport PyMem_Free
from _socket import gaierror
......@@ -58,8 +60,7 @@ cdef extern from "dnshelper.c":
pass
int gevent_make_sockaddr(char* hostp, int port, int flowinfo, int scope_id, sockaddr_in6* sa6)
void* malloc(int)
void free(void*)
void memset(void*, int, int)
......@@ -319,7 +320,7 @@ cdef class channel:
cares.ares_destroy(self.channel)
self.channel = NULL
def set_servers(self, servers=None):
cpdef set_servers(self, servers=None):
if not self.channel:
raise gaierror(cares.ARES_EDESTRUCTION, 'this ares channel has been destroyed')
if not servers:
......@@ -333,7 +334,7 @@ cdef class channel:
if length <= 0:
result = cares.ares_set_servers(self.channel, NULL)
else:
c_servers = <cares.ares_addr_node*>malloc(sizeof(cares.ares_addr_node) * length)
c_servers = <cares.ares_addr_node*>PyMem_Malloc(sizeof(cares.ares_addr_node) * length)
if not c_servers:
raise MemoryError
try:
......@@ -357,7 +358,7 @@ cdef class channel:
if index:
raise ValueError(strerror(index))
finally:
free(c_servers)
PyMem_Free(c_servers)
# this crashes c-ares
#def cancel(self):
......
......@@ -81,6 +81,7 @@ from . import hostname_types
from gevent._compat import string_types
from gevent._compat import iteritems
from gevent._patcher import import_patched
from gevent._config import config
__all__ = [
'Resolver',
......@@ -553,6 +554,8 @@ class Resolver(AbstractResolver):
self._resolver = _DualResolver()
if resolver._resolver is None:
resolver._resolver = self._resolver
if config.resolver_nameservers:
self._resolver.network_resolver.nameservers[:] = config.resolver_nameservers
# Different hubs in different threads could be sharing the same
# resolver.
assert isinstance(resolver._resolver, _DualResolver)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment