From f7fa75c0ab9f1b5e745bc55df52f24fbd9f53299 Mon Sep 17 00:00:00 2001
From: hansu650 <2788086371@qq.com>
Date: Tue, 25 Aug 2026 17:03:51 +0800
Subject: [PATCH] Fix socket close cancellation checkpoints
Fixes #1288.
---
docs/versionhistory.rst | 3 +++
src/anyio/_backends/_asyncio.py | 2 ++
src/anyio/_backends/_trio.py | 2 ++
tests/test_sockets.py | 15 +++++++++++++++
4 files changed, 22 insertions(+)
diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst
index 81f656aec..1a18928f7 100644
--- a/docs/versionhistory.rst
+++ b/docs/versionhistory.rst
@@ -68,6 +68,9 @@ This library adheres to `Semantic Versioning 2.0 `_.
- Fixed ``UNIXSocketStream.aclose()`` raising ``asyncio.InvalidStateError`` when a
concurrent receive or send operation had just been cancelled on the asyncio backend
(`#1267 `_; PR by @alloutflo)
+- Fixed socket ``aclose()`` implementations not checkpointing after closing on the
+ asyncio and Trio backends
+ (`#1288 `_; PR by @hansu650)
- Fixed the pytest plugin importing the deprecated ``_pytest.python.CallSpec2`` alias,
which triggers ``PytestRemovedIn10Warning`` on ``pytest>=9.2`` and crashes pytest at
startup when ``filterwarnings = error`` is configured
diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py
index 35b0cf371..9361c03a2 100644
--- a/src/anyio/_backends/_asyncio.py
+++ b/src/anyio/_backends/_asyncio.py
@@ -1453,6 +1453,8 @@ async def aclose(self) -> None:
if self._send_future and not self._send_future.done():
self._send_future.set_result(None)
+ await AsyncIOBackend.checkpoint()
+
class UNIXSocketStream(_RawSocketMixin, abc.UNIXSocketStream):
async def send_eof(self) -> None:
diff --git a/src/anyio/_backends/_trio.py b/src/anyio/_backends/_trio.py
index 2e67786e8..d6009a55a 100644
--- a/src/anyio/_backends/_trio.py
+++ b/src/anyio/_backends/_trio.py
@@ -467,6 +467,8 @@ async def aclose(self) -> None:
self._closed = True
self._trio_socket.close()
+ await trio.lowlevel.checkpoint()
+
def _convert_socket_error(self, exc: BaseException) -> NoReturn:
if isinstance(exc, trio.ClosedResourceError):
raise ClosedResourceError from exc
diff --git a/tests/test_sockets.py b/tests/test_sockets.py
index cc661b79a..e48d9d426 100644
--- a/tests/test_sockets.py
+++ b/tests/test_sockets.py
@@ -37,6 +37,7 @@
from anyio import (
BrokenResourceError,
BusyResourceError,
+ CancelScope,
ClosedResourceError,
EndOfStream,
Event,
@@ -54,6 +55,7 @@
create_unix_datagram_socket,
create_unix_listener,
fail_after,
+ get_cancelled_exc_class,
getaddrinfo,
getnameinfo,
move_on_after,
@@ -1499,6 +1501,19 @@ async def operate() -> None:
if client is not None:
await client.aclose()
+ async def test_aclose_checkpoints_when_cancelled(
+ self, server_sock: socket.socket, socket_path: Path
+ ) -> None:
+ stream = await connect_unix(socket_path)
+ raw_socket = stream.extra(SocketAttribute.raw_socket)
+
+ with CancelScope() as scope:
+ scope.cancel()
+ with pytest.raises(get_cancelled_exc_class()):
+ await stream.aclose()
+
+ assert raw_socket.fileno() == -1
+
async def test_receive_after_close(
self, server_sock: socket.socket, socket_path: Path
) -> None: