Skip to content

Commit

Permalink
Merge ea8073e into beb98ce
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Oct 13, 2022
2 parents beb98ce + ea8073e commit f1aa198
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 12 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Expand Up @@ -350,11 +350,10 @@ jobs:
run: |
python -mgevent.tests --second-chance $G_USE_COV --ignore tests_that_dont_use_resolver.txt
- name: "Tests: leakchecks"
# Run the leaktests; this seems to be extremely slow on Python 3.7
# XXX: Figure out why. Can we reproduce locally?
# Run the leaktests;
# This is incredibly important and we MUST have an environment that successfully passes
# these tests.
if: matrix.python-version == 2.7 && startsWith(runner.os, 'Linux')
if: (matrix.python-version == 2.7 || startsWith(matrix.python-version, '3.11')) && startsWith(runner.os, 'Linux')
env:
GEVENTTEST_LEAKCHECK: 1
run: |
Expand Down
9 changes: 9 additions & 0 deletions src/gevent/resolver/__init__.py
Expand Up @@ -135,6 +135,15 @@ class AbstractResolver(object):
and k not in ('SOCK_CLOEXEC', 'SOCK_MAX_SIZE')
}

def close(self):
"""
Release resources held by this object.
Subclasses that define resources should override.
.. versionadded:: NEXT
"""

@staticmethod
def fixup_gaierror(func):
import functools
Expand Down
15 changes: 14 additions & 1 deletion src/gevent/resolver/ares.py
Expand Up @@ -4,6 +4,7 @@
"""
from __future__ import absolute_import, print_function, division
import os
import warnings

from _socket import gaierror
from _socket import herror
Expand Down Expand Up @@ -116,12 +117,17 @@ class Resolver(AbstractResolver):
Handling of localhost and broadcast names is now more consistent.
.. versionchanged:: NEXT
Now has a ``__del__`` method that warns if the object is destroyed
without being properly closed.
.. _c-ares: http://c-ares.haxx.se
"""

cares_class = channel

def __init__(self, hub=None, use_environ=True, **kwargs):
AbstractResolver.__init__(self)
if hub is None:
hub = get_hub()
self.hub = hub
Expand All @@ -134,7 +140,7 @@ def __init__(self, hub=None, use_environ=True, **kwargs):
self.cares = self.cares_class(hub.loop, **kwargs)
self.pid = os.getpid()
self.params = kwargs
self.fork_watcher = hub.loop.fork(ref=False)
self.fork_watcher = hub.loop.fork(ref=False) # We shouldn't keep the loop alive
self.fork_watcher.start(self._on_fork)

def __repr__(self):
Expand All @@ -149,11 +155,18 @@ def _on_fork(self):
self.pid = pid

def close(self):
AbstractResolver.close(self)
if self.cares is not None:
self.hub.loop.run_callback(self.cares.destroy)
self.cares = None
self.fork_watcher.stop()

def __del__(self):
if self.cares is not None:
warnings.warn("cares Resolver destroyed while not closed",
ResourceWarning)
self.close()

def _gethostbyname_ex(self, hostname_bytes, family):
while True:
ares = self.cares
Expand Down
8 changes: 4 additions & 4 deletions src/gevent/resolver/cares.pyx
Expand Up @@ -412,6 +412,9 @@ cdef class channel:
return '<%s at 0x%x _timer=%r _watchers[%s]>' % args

def destroy(self):
self.__destroy()

cdef __destroy(self):
if self.channel:
# XXX ares_library_cleanup?
cares.ares_destroy(self.channel)
Expand All @@ -421,10 +424,7 @@ cdef class channel:
self.loop = None

def __dealloc__(self):
if self.channel:
# XXX ares_library_cleanup?
cares.ares_destroy(self.channel)
self.channel = NULL
self.__destroy()

cpdef set_servers(self, servers=None):
if not self.channel:
Expand Down
7 changes: 4 additions & 3 deletions src/gevent/testing/leakcheck.py
Expand Up @@ -21,7 +21,6 @@

import sys
import gc
import types
from functools import wraps
import unittest

Expand Down Expand Up @@ -52,8 +51,10 @@ class and specify variants of behaviour (such as pool sizes).

class _RefCountChecker(object):

# Some builtin things that we ignore
IGNORED_TYPES = (tuple, dict, types.FrameType, types.TracebackType)
# Some builtin things that we ignore.
# For awhile, we also ignored types.FrameType and types.TracebackType,
# but those are important and often involved in leaks.
IGNORED_TYPES = (tuple, dict,)
try:
CALLBACK_KIND = gevent.core.callback
except AttributeError:
Expand Down
1 change: 1 addition & 0 deletions src/gevent/tests/test__ares_timeout.py
Expand Up @@ -34,6 +34,7 @@ def reader():

r = Resolver(servers=[address[0]], timeout=0.001, tries=1,
udp_port=address[-1])
self._close_on_teardown(r)

with self.assertRaisesRegex(socket.herror, "ARES_ETIMEOUT"):
r.gethostbyname('www.google.com')
Expand Down
2 changes: 1 addition & 1 deletion src/gevent/tests/test__environ.py
Expand Up @@ -4,7 +4,7 @@
import gevent.core
import subprocess

if sys.argv[1:] == []:
if not sys.argv[1:]:
os.environ['GEVENT_BACKEND'] = 'select'
# (not in Py2) pylint:disable=consider-using-with
popen = subprocess.Popen([sys.executable, __file__, '1'])
Expand Down

0 comments on commit f1aa198

Please sign in to comment.