From: Bob Halley Date: Thu, 23 Jan 2025 20:07:10 +0000 (-0800) Subject: Do not leak fds when using a selector [#1177]. (#1178) X-Git-Tag: v2.8.0rc1~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2b81a2edf4da1b8f052e573e93e3067b5bb7d11;p=thirdparty%2Fdnspython.git Do not leak fds when using a selector [#1177]. (#1178) --- diff --git a/dns/query.py b/dns/query.py index 6006a737..5af4a36c 100644 --- a/dns/query.py +++ b/dns/query.py @@ -240,22 +240,22 @@ def _wait_for(fd, readable, writable, _, expiration): if readable and isinstance(fd, ssl.SSLSocket) and fd.pending() > 0: return True - sel = selectors.DefaultSelector() - events = 0 - if readable: - events |= selectors.EVENT_READ - if writable: - events |= selectors.EVENT_WRITE - if events: - sel.register(fd, events) # pyright: ignore - if expiration is None: - timeout = None - else: - timeout = expiration - time.time() - if timeout <= 0.0: + with selectors.DefaultSelector() as sel: + events = 0 + if readable: + events |= selectors.EVENT_READ + if writable: + events |= selectors.EVENT_WRITE + if events: + sel.register(fd, events) # pyright: ignore + if expiration is None: + timeout = None + else: + timeout = expiration - time.time() + if timeout <= 0.0: + raise dns.exception.Timeout + if not sel.select(timeout): raise dns.exception.Timeout - if not sel.select(timeout): - raise dns.exception.Timeout def _wait_for_readable(s, expiration): diff --git a/dns/quic/_sync.py b/dns/quic/_sync.py index d6e41282..18f9d05b 100644 --- a/dns/quic/_sync.py +++ b/dns/quic/_sync.py @@ -133,25 +133,27 @@ class SyncQuicConnection(BaseQuicConnection): def _worker(self): try: - sel = selectors.DefaultSelector() - sel.register(self._socket, selectors.EVENT_READ, self._read) - sel.register(self._receive_wakeup, selectors.EVENT_READ, self._drain_wakeup) - while not self._done: - (expiration, interval) = self._get_timer_values(False) - items = sel.select(interval) - for key, _ in items: - key.data() - with self._lock: - self._handle_timer(expiration) - self._handle_events() - with self._lock: - datagrams = self._connection.datagrams_to_send(time.time()) - for datagram, _ in datagrams: - try: - self._socket.send(datagram) - except BlockingIOError: - # we let QUIC handle any lossage - pass + with selectors.DefaultSelector() as sel: + sel.register(self._socket, selectors.EVENT_READ, self._read) + sel.register( + self._receive_wakeup, selectors.EVENT_READ, self._drain_wakeup + ) + while not self._done: + (expiration, interval) = self._get_timer_values(False) + items = sel.select(interval) + for key, _ in items: + key.data() + with self._lock: + self._handle_timer(expiration) + self._handle_events() + with self._lock: + datagrams = self._connection.datagrams_to_send(time.time()) + for datagram, _ in datagrams: + try: + self._socket.send(datagram) + except BlockingIOError: + # we let QUIC handle any lossage + pass except Exception: # Eat all exceptions as we have no way to pass them back to the # caller currently. It might be nice to fix this in the future.