Skip to content

Commit 111dd16

Browse files
committed
Streamline handling of async loop exit
1 parent ac78304 commit 111dd16

File tree

2 files changed

+28
-23
lines changed

2 files changed

+28
-23
lines changed

trio_asyncio/_base.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,16 @@ async def _main_loop(self, task_status=trio.TASK_STATUS_IGNORED):
631631
sniffio.current_async_library_cvar.set("asyncio")
632632

633633
try:
634-
while not self._stopped.is_set():
635-
await self._main_loop_one()
634+
# The shield here ensures that if the context surrounding
635+
# the loop is cancelled, we keep processing callbacks
636+
# until we reach the callback inserted by stop().
637+
# There's a call to stop() in the finally block of
638+
# open_loop(), and we're not shielding the body of the
639+
# open_loop() context, so this should be safe against
640+
# deadlocks.
641+
with trio.CancelScope(shield=True):
642+
while not self._stopped.is_set():
643+
await self._main_loop_one()
636644
except StopAsyncIteration:
637645
# raised by .stop_me() to interrupt the loop
638646
pass
@@ -693,16 +701,20 @@ async def _main_loop_exit(self):
693701
if self._closed:
694702
return
695703

696-
self.stop()
697-
await self.wait_stopped()
698-
699-
while True:
700-
try:
701-
await self._main_loop_one(no_wait=True)
702-
except trio.WouldBlock:
703-
break
704-
except StopAsyncIteration:
705-
pass
704+
with trio.CancelScope(shield=True):
705+
self.stop()
706+
await self.wait_stopped()
707+
708+
# Drain all remaining callbacks, even those after an initial
709+
# call to stop(). This avoids a deadlock if stop() was called
710+
# again during unwinding.
711+
while True:
712+
try:
713+
await self._main_loop_one(no_wait=True)
714+
except trio.WouldBlock:
715+
break
716+
except StopAsyncIteration:
717+
pass
706718

707719
# Kill off unprocessed work
708720
self._cancel_fds()

trio_asyncio/_loop.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,6 @@ async def async_main(*args):
390390

391391
# TODO: make sure that there is no asyncio loop already running
392392

393-
def _main_loop_exit(self):
394-
super()._main_loop_exit()
395-
self._thread = None
396-
397393
async with trio.open_nursery() as nursery:
398394
loop = TrioEventLoop(queue_len=queue_len)
399395
old_loop = current_loop.set(loop)
@@ -404,14 +400,11 @@ def _main_loop_exit(self):
404400
await yield_(loop)
405401
finally:
406402
try:
407-
await loop.stop().wait()
403+
await loop._main_loop_exit()
408404
finally:
409-
try:
410-
await loop._main_loop_exit()
411-
finally:
412-
loop.close()
413-
nursery.cancel_scope.cancel()
414-
current_loop.reset(old_loop)
405+
loop.close()
406+
nursery.cancel_scope.cancel()
407+
current_loop.reset(old_loop)
415408

416409

417410
def run(proc, *args, queue_len=None):

0 commit comments

Comments
 (0)