From 3a6dd4a2dee2910afdaf94f2553c72884eb0d802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francis=20Clairicia-Rose-Claire-Jos=C3=A9phine?= Date: Mon, 27 Nov 2023 12:16:44 +0100 Subject: [PATCH] AsyncSocket: shutdown() was not checking current running loop (#172) --- pyproject.toml | 2 +- src/easynetwork/lowlevel/asyncio/socket.py | 11 +++++++---- src/easynetwork/lowlevel/asyncio/tasks.py | 4 ++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e0819be4..80d2cf15 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -202,7 +202,7 @@ enable_error_code = ["truthy-bool", "ignore-without-code", "unused-awaitable"] [tool.pytest.ini_options] asyncio_mode = "strict" # Avoid some unwanted behaviour -addopts = "--strict-markers" +addopts = "--strict-markers -p 'no:anyio'" # hatch CLI dependencies installs anyio minversion = "7.1.2" testpaths = ["tests"] norecursedirs = ["scripts"] diff --git a/src/easynetwork/lowlevel/asyncio/socket.py b/src/easynetwork/lowlevel/asyncio/socket.py index 11ffe359..5d79ed99 100644 --- a/src/easynetwork/lowlevel/asyncio/socket.py +++ b/src/easynetwork/lowlevel/asyncio/socket.py @@ -160,14 +160,17 @@ async def recvfrom(self, bufsize: int, /) -> tuple[bytes, _socket._RetAddress]: return await self.__loop.sock_recvfrom(socket, bufsize) async def shutdown(self, how: int, /) -> None: - socket: _socket.socket = self.__check_not_closed() + # Checks if we are within the bound loop + TaskUtils.check_current_asyncio_task(self.__loop) + if how in {_socket.SHUT_RDWR, _socket.SHUT_WR}: while (waiter := self.__waiters.get("send")) is not None: try: await asyncio.shield(waiter) finally: - waiter = None # Breack cyclic reference with raised exception + waiter = None # Break cyclic reference with raised exception + socket: _socket.socket = self.__check_not_closed() socket.shutdown(how) await asyncio.sleep(0) @@ -177,9 +180,9 @@ def __conflict_detection(self, task_id: _SocketTaskId, *, abort_errno: int = _er raise _utils.error_from_errno(_errno.EBUSY) # Checks if we are within the bound loop - TaskUtils.current_asyncio_task(self.__loop) # type: ignore[unused-awaitable] + TaskUtils.check_current_asyncio_task(self.__loop) - with CancelScope() as scope, contextlib.ExitStack() as stack: + with contextlib.ExitStack() as stack, CancelScope() as scope: self.__scopes.add(scope) stack.callback(self.__scopes.discard, scope) diff --git a/src/easynetwork/lowlevel/asyncio/tasks.py b/src/easynetwork/lowlevel/asyncio/tasks.py index 2713033f..07e2fb04 100644 --- a/src/easynetwork/lowlevel/asyncio/tasks.py +++ b/src/easynetwork/lowlevel/asyncio/tasks.py @@ -310,6 +310,10 @@ def __cancel_task_unless_done(task: asyncio.Task[Any], cancel_msg: str | None) - @final class TaskUtils: + @staticmethod + def check_current_asyncio_task(loop: asyncio.AbstractEventLoop | None = None) -> None: + _ = TaskUtils.current_asyncio_task(loop=loop) + @staticmethod def current_asyncio_task(loop: asyncio.AbstractEventLoop | None = None) -> asyncio.Task[Any]: t: asyncio.Task[Any] | None = asyncio.current_task(loop=loop)