diff --git a/CHANGES/7798.bugfix b/CHANGES/7798.bugfix new file mode 100644 index 00000000000..c7d35056bea --- /dev/null +++ b/CHANGES/7798.bugfix @@ -0,0 +1 @@ +Fix infinite loop releasing the connection when the writer is not finished diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index 8271f70e445..3fef2b8a1fe 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -916,10 +916,12 @@ def _response_eof(self) -> None: ): return + self._cleanup_writer() self._release_connection() + else: + self._cleanup_writer() self._closed = True - self._cleanup_writer() @property def closed(self) -> bool: @@ -968,13 +970,23 @@ def raise_for_status(self) -> None: headers=self.headers, ) + def _cleanup_on_writer_done(self, _: "asyncio.Future[None]") -> None: + """Cleanup writer and release connection. + + This is called as a callback when the writer finishes + in the event _release_connection was called + before the writer is done. + """ + self._writer = None + self._release_connection() + def _release_connection(self) -> None: if self._connection is not None: if self._writer is None: self._connection.release() self._connection = None else: - self._writer.add_done_callback(lambda f: self._release_connection()) + self._writer.add_done_callback(self._cleanup_on_writer_done) async def _wait_released(self) -> None: if self._writer is not None: