Skip to content

Commit c76264d

Browse files
committed
Streamline handling of async loop exit
1 parent 04947c3 commit c76264d

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
@@ -687,8 +687,16 @@ async def _main_loop(self, task_status=trio.TASK_STATUS_IGNORED):
687687
sniffio.current_async_library_cvar.set("asyncio")
688688

689689
try:
690-
while not self._stopped.is_set():
691-
await self._main_loop_one()
690+
# The shield here ensures that if the context surrounding
691+
# the loop is cancelled, we keep processing callbacks
692+
# until we reach the callback inserted by stop().
693+
# There's a call to stop() in the finally block of
694+
# open_loop(), and we're not shielding the body of the
695+
# open_loop() context, so this should be safe against
696+
# deadlocks.
697+
with trio.CancelScope(shield=True):
698+
while not self._stopped.is_set():
699+
await self._main_loop_one()
692700
except StopAsyncIteration:
693701
# raised by .stop_me() to interrupt the loop
694702
pass
@@ -745,16 +753,20 @@ async def _main_loop_exit(self):
745753
if self._closed:
746754
return
747755

748-
self.stop()
749-
await self.wait_stopped()
750-
751-
while True:
752-
try:
753-
await self._main_loop_one(no_wait=True)
754-
except trio.WouldBlock:
755-
break
756-
except StopAsyncIteration:
757-
pass
756+
with trio.CancelScope(shield=True):
757+
self.stop()
758+
await self.wait_stopped()
759+
760+
# Drain all remaining callbacks, even those after an initial
761+
# call to stop(). This avoids a deadlock if stop() was called
762+
# again during unwinding.
763+
while True:
764+
try:
765+
await self._main_loop_one(no_wait=True)
766+
except trio.WouldBlock:
767+
break
768+
except StopAsyncIteration:
769+
pass
758770

759771
# Kill off unprocessed work
760772
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)