From 3773d9a0e34c9213a7989a0d08a88470a16ba3c4 Mon Sep 17 00:00:00 2001 From: Zo Bot Date: Fri, 19 Jun 2026 01:28:01 +0000 Subject: [PATCH] narrow bare except around _try_inline_read to Exception in five readers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bare 'except:' in read_until_regex, read_until, read_bytes, read_into, and read_until_close was wrapping self._try_inline_read() so the caller could install a done_callback that pulls .exception() off the future and silence the 'Future exception was never retrieved' warning before re-raising. That bare except also caught BaseException, so a KeyboardInterrupt, SystemExit, asyncio.CancelledError, MemoryError, or RecursionError raised inside _try_inline_read() (or any of the per-call setup just above the try block, like re.compile()) was intercepted, queued the done_callback, then re-raised — meaning Ctrl-C during a network read briefly invoked a useless future.add_done_callback on its way out instead of cancelling the awaitable immediately. Narrowing to 'except Exception:' preserves the documented intent (silence the unexamined-future warning for ordinary failures like UnsatisfiableReadError, StreamClosedError, OSError, ValueError from re.compile, and LookupError from a bad regex) while letting real shutdown signals propagate straight through to the awaiting coroutine. --- tornado/iostream.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tornado/iostream.py b/tornado/iostream.py index 53e81fff3..89814c0b6 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -346,7 +346,7 @@ def read_until_regex( gen_log.info("Unsatisfiable read, closing connection: %s" % e) self.close(exc_info=e) return future - except: + except Exception: # Ensure that the future doesn't log an error because its # failure was never examined. future.add_done_callback(lambda f: f.exception()) @@ -383,7 +383,7 @@ def read_until( gen_log.info("Unsatisfiable read, closing connection: %s" % e) self.close(exc_info=e) return future - except: + except Exception: future.add_done_callback(lambda f: f.exception()) raise return future @@ -411,7 +411,7 @@ def read_bytes(self, num_bytes: int, partial: bool = False) -> Awaitable[bytes]: self._read_partial = partial try: self._try_inline_read() - except: + except Exception: future.add_done_callback(lambda f: f.exception()) raise return future @@ -456,7 +456,7 @@ def read_into(self, buf: bytearray, partial: bool = False) -> Awaitable[int]: try: self._try_inline_read() - except: + except Exception: future.add_done_callback(lambda f: f.exception()) raise return future @@ -486,7 +486,7 @@ def read_until_close(self) -> Awaitable[bytes]: self._read_until_close = True try: self._try_inline_read() - except: + except Exception: future.add_done_callback(lambda f: f.exception()) raise return future