Skip to content

Commit 30704b9

Browse files
committed
Cancel aio and trio tasks simultaneously
1 parent 845af47 commit 30704b9

File tree

2 files changed

+20
-26
lines changed

2 files changed

+20
-26
lines changed

tests/test_trio_asyncio.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ async def trio_sleeper(key):
8686
tasks.append(asyncio.ensure_future(aio_sleeper("aio early")))
8787
loop.run_trio_task(trio_sleeper, "trio early")
8888

89-
assert record[0] == "aio early"
90-
assert set(record[1:]) == {"trio early", "trio late"}
89+
assert set(record) == {"aio early", "trio early", "trio late"}
9190
assert len(tasks) == 2 and tasks[0].done() and not tasks[1].done()
9291

9392
# Suppress "Task was destroyed but it was pending!" message

trio_asyncio/_loop.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -386,16 +386,16 @@ async def open_loop(queue_len=None):
386386
387387
Exiting the context manager will attempt to do an orderly shutdown
388388
of the tasks it contains, analogously to :func:`asyncio.run`.
389-
asyncio-flavored tasks are cancelled and awaited first, then
390-
Trio-flavored tasks that were started using
391-
:meth:`~BaseTrioEventLoop.trio_as_future` or
392-
:meth:`~BaseTrioEventLoop.run_trio_task`. All
389+
Both asyncio-flavored tasks and Trio-flavored tasks (the latter
390+
started using :meth:`~BaseTrioEventLoop.trio_as_future`,
391+
:meth:`~BaseTrioEventLoop.run_trio_task`, :func:`trio_as_aio`,
392+
etc) are cancelled simultaneously, and the loop waits for them to
393+
exit in response to this cancellation before proceeding. All
393394
:meth:`~asyncio.loop.call_soon` callbacks that are submitted
394-
before exiting the context manager will run before starting
395-
this shutdown sequence, and all callbacks that are submitted
396-
before the last task exits will run before the loop closes.
397-
The exact point at which the loop stops running callbacks is
398-
not specified.
395+
before exiting the context manager will run before starting this
396+
shutdown sequence, and all callbacks that are submitted before the
397+
last task exits will run before the loop closes. The exact point
398+
at which the loop stops running callbacks is not specified.
399399
400400
.. warning:: As with :func:`asyncio.run`, asyncio-flavored tasks
401401
that are started *after* exiting the context manager (such as by
@@ -447,27 +447,22 @@ async def wait_for_sync():
447447
await loop.wait_stopped()
448448
sync_nursery.cancel_scope.cancel()
449449

450-
# Cancel and wait on all currently-running asyncio tasks.
450+
# Cancel and wait on all currently-running tasks.
451+
# Exiting the tasks_nursery will wait for the Trio tasks
452+
# automatically; we mix in the asyncio tasks by scheduling
453+
# a call to run_aio_future() for each one. It's important
454+
# not to wait on one kind of task before the other, so that
455+
# we support Trio tasks that need to run some asyncio
456+
# code during teardown as well as the opposite.
451457
# Like asyncio.run(), we don't bother cancelling and waiting
452-
# on any additional tasks that these tasks start as they
458+
# on any additional asyncio tasks that these tasks start as they
453459
# unwind.
454460
if sys.version_info >= (3, 7):
455461
aio_tasks = asyncio.all_tasks(loop)
456462
else:
457463
aio_tasks = {t for t in asyncio.Task.all_tasks(loop) if not t.done()}
458-
if aio_tasks:
459-
# Start one Trio task to wait for each still-running
460-
# asyncio task. This provides better exception
461-
# propagation than using asyncio.gather().
462-
async with trio.open_nursery() as aio_cancel_nursery:
463-
for task in aio_tasks:
464-
aio_cancel_nursery.start_soon(run_aio_future, task)
465-
aio_cancel_nursery.cancel_scope.cancel()
466-
467-
# If there are any trio_as_aio tasks still going after
468-
# the cancellation of asyncio tasks above, this will
469-
# cancel them, and exiting the tasks_nursery block
470-
# will wait for them to exit.
464+
for task in aio_tasks:
465+
tasks_nursery.start_soon(run_aio_future, task)
471466
tasks_nursery.cancel_scope.cancel()
472467
finally:
473468
try:

0 commit comments

Comments
 (0)