From 21eee9163f53a106734189704617542a00522f7e Mon Sep 17 00:00:00 2001 From: oliver Date: Sat, 20 Jun 2026 17:08:26 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20make=20test=5Fdepends=5Fdeadlock=20?= =?UTF-8?q?more=20co-operative?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures that the threads which are blocking up the threadpool eventually exit when in failure mode. --- tests/test_depends_deadlock.py | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/tests/test_depends_deadlock.py b/tests/test_depends_deadlock.py index c3d2ee075..2178c81f0 100644 --- a/tests/test_depends_deadlock.py +++ b/tests/test_depends_deadlock.py @@ -1,5 +1,4 @@ import asyncio -import multiprocessing import threading import time from collections.abc import Iterator @@ -36,36 +35,14 @@ class Item(BaseModel): # of the model and the cleanup of the Depends @app.get("/deadlock", response_model=Item) def get_deadlock(dep: None = Depends(release_resource)) -> Item: - mutex.acquire() + mutex.acquire(timeout=10) return Item(name="foo", id=1) -# NOTE: the failure mode here can cause the test suite to hang. -# Since the default threadpool is a global which is not easily patched -# (and doing so would make the test somewhat fragile/pointless) -# we need to use a subprocess to isolate the bad behaviour. -# If you are struggling to debug, comment out this function and rename -# the impl_ version to test_depends_deadlock -def test_depends_deadlock() -> None: - - proc = multiprocessing.Process(target=impl_test_depends_deadlock, daemon=True) - proc.start() - proc.join(timeout=10) - - try: - assert not proc.is_alive(), ( - "Process is still alive after timeout, likely due to a deadlock" - ) - finally: - proc.kill() # Ensure the process is terminated if it's still alive - - assert proc.exitcode == 0, "Process did not exit cleanly, see logs for details" - - # Fire off 100 requests in parallel(ish) in order to create contention # over the shared resource (simulating a fastapi server that interacts with # a database connection pool). -def impl_test_depends_deadlock() -> None: +def test_depends_deadlock() -> None: async def make_request(client: AsyncClient): await client.get("/deadlock")