From f3a18003e66e4ae047ff1dd7bb3020931b5c78e2 Mon Sep 17 00:00:00 2001 From: oliver Date: Wed, 17 Jun 2026 21:20:22 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20Add=20timeout=20to=20anyio=20deadlo?= =?UTF-8?q?ck=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures that if an anyio deadlock issue is re-introduced the test suite will fail in a helpful way rather than just hanging. --- tests/test_concurrency.py | 7 +++++-- tests/test_depends_deadlock.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py index 9e9fd9bff..5a27e1904 100644 --- a/tests/test_concurrency.py +++ b/tests/test_concurrency.py @@ -1,3 +1,4 @@ +import asyncio import contextlib import time from collections.abc import Iterator @@ -40,7 +41,7 @@ async def test_contextmanager_in_threadpool() -> None: @pytest.mark.usefixtures("reset_teardown_limiter") async def test_competing_acquire_release() -> None: """Check that the main threadpool does not block the teardown threadpool.""" - pool_size = anyio.to_thread.current_default_thread_limiter().total_tokens + pool_size = int(anyio.to_thread.current_default_thread_limiter().total_tokens) acquirable = False acquired = [] @@ -63,6 +64,8 @@ async def test_competing_acquire_release() -> None: # The threadpool should now be full of threads waiting to acquire # The release function should be able to run without being blocked by acquires - await concurrency.run_in_teardown_threadpool(release) + await asyncio.wait_for( + concurrency.run_in_teardown_threadpool(release), timeout=10 + ) assert len(acquired) == pool_size diff --git a/tests/test_depends_deadlock.py b/tests/test_depends_deadlock.py index 011cb529b..76e44cf68 100644 --- a/tests/test_depends_deadlock.py +++ b/tests/test_depends_deadlock.py @@ -11,7 +11,7 @@ from pydantic import BaseModel mutex = threading.Lock() -# Simulate releaasing a pooled resource in the teardown of a Depends, +# Simulate releasing a pooled resource in the teardown of a Depends, # which in reality is usually a database connection or similar. def release_resource() -> Iterator[None]: try: @@ -53,4 +53,4 @@ def test_depends_deadlock() -> None: tasks = [make_request(aclient) for _ in range(100)] await asyncio.gather(*tasks) - asyncio.run(run_requests()) + asyncio.run(asyncio.wait_for(run_requests(), timeout=10))