diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 22147451fa7ebd..eb9ee4641dc7cc 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -864,16 +864,37 @@ def close(self): self._closing = True self._loop._remove_reader(self._sock_fd) if not self._buffer: - self._conn_lost += 1 self._loop._remove_writer(self._sock_fd) + self._conn_lost += 1 self._loop.call_soon(self._call_connection_lost, None) def __del__(self, _warn=warnings.warn): if self._sock is not None: - _warn(f"unclosed transport {self!r}", ResourceWarning, source=self) + if self._protocol_connected: + self._protocol_connected = False + _warn(f"unclosed transport {self!r}", ResourceWarning, source=self) + + if self._buffer: + self._buffer.clear() + self._loop._remove_writer(self._sock_fd) + + if not self._closing: + self._closing = True + self._loop._remove_reader(self._sock_fd) + + self._conn_lost += 1 + + self._sock_fd = -1 self._sock.close() - if self._server is not None: - self._server._detach(self) + self._sock = None + + self._protocol = None + self._loop = None + + server = self._server + if server is not None: + self._server = None + server._detach(self) def _fatal_error(self, exc, message='Fatal error on transport'): # Should be called from exception handler only. @@ -904,8 +925,10 @@ def _force_close(self, exc): def _call_connection_lost(self, exc): try: if self._protocol_connected: + self._protocol_connected = False self._protocol.connection_lost(exc) finally: + self._sock_fd = -1 self._sock.close() self._sock = None self._protocol = None diff --git a/Misc/NEWS.d/next/Library/2025-02-14-18-04-47.gh-issue-130141.Iwwa0O.rst b/Misc/NEWS.d/next/Library/2025-02-14-18-04-47.gh-issue-130141.Iwwa0O.rst new file mode 100644 index 00000000000000..65e0dd92804850 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-14-18-04-47.gh-issue-130141.Iwwa0O.rst @@ -0,0 +1,2 @@ +Fix asyncio selector stall if :class:`!asyncio._SelectorTransport` is +resurrected from GC for .close() after the fd has been reused.