From ac35da6d9c6debabc40928f7dedccc5680b3adf1 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Fri, 14 Aug 2026 15:41:51 +0200 Subject: [PATCH] lib.AsyncRunner: Fix asyncio.Event() for Python 3.12+ AsyncRunner is currently unused. This bug was detected and fixed by AI. asyncio.Event() raises RuntimeError on Python 3.12+ when created outside a running event loop. It is created in the sync portion of loop_in_thread(), before the threaded loop is up. The fix is to move the Event creation inside the async main() coroutine and pass it back via a second future. It replaces the fragile as_completed loop with sequential result() calls, so failures are immediately visible rather than causing a silent thread hang. Assisted-by: unsloth/Qwen3.6-27B-MTP-GGUF:Q4_K_M with pi.dev v0.84.1 Signed-off-by: Jan Lindemann --- src/python/jw/pkg/lib/AsyncRunner.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/python/jw/pkg/lib/AsyncRunner.py b/src/python/jw/pkg/lib/AsyncRunner.py index fadfbbcd..d6f181ba 100644 --- a/src/python/jw/pkg/lib/AsyncRunner.py +++ b/src/python/jw/pkg/lib/AsyncRunner.py @@ -17,25 +17,23 @@ def loop_in_thread() -> Generator[asyncio.AbstractEventLoop, None, None]: loop_fut: concurrent.futures.Future[asyncio.AbstractEventLoop] = ( concurrent.futures.Future() ) - - stop_event = asyncio.Event() + stop_fut: concurrent.futures.Future[asyncio.Event] = (concurrent.futures.Future()) async def main() -> None: loop_fut.set_result(asyncio.get_running_loop()) + stop_event = asyncio.Event() + stop_fut.set_result(stop_event) await stop_event.wait() with concurrent.futures.ThreadPoolExecutor(max_workers = 1) as tpe: complete_fut = tpe.submit(asyncio.run, main()) - - for fut in concurrent.futures.as_completed((loop_fut, complete_fut)): - if fut is loop_fut: - loop = loop_fut.result() - try: - yield loop - finally: - loop.call_soon_threadsafe(stop_event.set) - else: - fut.result() + loop = loop_fut.result() + stop_event = stop_fut.result() + try: + yield loop + finally: + loop.call_soon_threadsafe(stop_event.set) + complete_fut.result() class AsyncRunner: -- 2.55.0