From d817f1a65826eabb69bb87c6e2b7aa63fb69b876 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Wed, 1 Dec 2021 22:05:23 -0500 Subject: [PATCH] Add a nursery "exited" signal Use a `trio.Event` to enable nursery closure detection such that core runtime tasks can be notified when a local nursery exits and allow shutdown protocols to operate without close-before-terminate issues (such as IPC channel closure during remote peer cancellation). --- tractor/_supervise.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tractor/_supervise.py b/tractor/_supervise.py index 1259be6..3f381ef 100644 --- a/tractor/_supervise.py +++ b/tractor/_supervise.py @@ -52,6 +52,7 @@ class ActorNursery: self.cancelled: bool = False self._join_procs = trio.Event() self.errors = errors + self.exited = trio.Event() async def start_actor( self, @@ -207,7 +208,8 @@ class ActorNursery: # spawn cancel tasks for each sub-actor assert portal - nursery.start_soon(portal.cancel_actor) + if portal.channel.connected(): + nursery.start_soon(portal.cancel_actor) # if we cancelled the cancel (we hung cancelling remote actors) # then hard kill all sub-processes @@ -401,18 +403,23 @@ async def open_nursery( async with open_root_actor(**kwargs) as actor: assert actor is current_actor() - # try: + try: + async with _open_and_supervise_one_cancels_all_nursery( + actor + ) as anursery: + yield anursery + finally: + anursery.exited.set() + + else: # sub-nursery case + + try: async with _open_and_supervise_one_cancels_all_nursery( actor ) as anursery: yield anursery - - else: # sub-nursery case - - async with _open_and_supervise_one_cancels_all_nursery( - actor - ) as anursery: - yield anursery + finally: + anursery.exited.set() finally: log.debug("Nursery teardown complete")