Merge the supervise error handlers into one

Step B2 of the `._ria_nursery` removal (issue #477; see
`ai/conc-anal/ria_nursery_removal_plan.md`). With the 2ndary
nursery gone (step B), the two nested error handlers in
`_open_and_supervise_one_cancels_all_nursery` collapse to one,

- the outer `except (Exception, BaseExceptionGroup,
  trio.Cancelled)` existed to catch errors bubbling from the
  old `._ria_nursery.__aexit__` reaper-group; that nursery no
  longer exists.
- trace shows the outer handler's `raise` was already DEAD: the
  inner handler records `errors[uid]` as its first action, so
  `errors` is always non-empty by the time anything could reach
  the outer handler, and the `finally`'s raise-from-`errors`
  always superseded the outer `raise`.
- so fold both into a single `except BaseException as
  _scope_err` guarding the lone daemon nursery; the `finally`
  (unchanged) still raises the collected `errors` as a single
  exc or `BaseExceptionGroup`.
- drop the now-unused `outer_err`/`inner_err` locals.

Behaviour-preserving (net ~30 lines lighter); the big diff is
the one-level de-indent of the handler body. The two remaining
`maybe_wait_for_debugger()` guards collapse to the single
pre-teardown wait.

Prompt-IO: ai/prompt-io/claude/20260702T222544Z_9201a2ed_prompt_io.md

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
drop_ria_nursery
Gud Boi 2026-07-02 18:33:17 -04:00
parent b14bc8e273
commit e617b498ec
1 changed files with 115 additions and 145 deletions

View File

@ -623,9 +623,6 @@ async def _open_and_supervise_one_cancels_all_nursery(
# normally don't need to show user by default
__tracebackhide__: bool = hide_tb
outer_err: BaseException|None = None
inner_err: BaseException|None = None
# the collection of errors retreived from spawned sub-actors
errors: dict[tuple[str, str], BaseException] = {}
@ -644,7 +641,6 @@ async def _open_and_supervise_one_cancels_all_nursery(
da_nursery,
errors
)
try:
try:
# spawning of actors happens in the caller's scope
# after we yield upwards
@ -664,9 +660,19 @@ async def _open_and_supervise_one_cancels_all_nursery(
# each, one reaper task per child.
await _reap_ria_portals(an, errors)
except BaseException as _inner_err:
inner_err = _inner_err
errors[actor.aid.uid] = inner_err
# Single one-cancels-all handler for the (now single)
# daemon nursery. Pre-#477 a 2ndary `._ria_nursery`
# required a separate *outer* handler to catch errors
# bubbling from its task-reaping `__aexit__`; with that
# nursery gone this lone handler covers every scope
# error. NB: we deliberately do NOT re-raise here — the
# `finally` below raises the collected `errors` (as a
# single exc or `BaseExceptionGroup`), which already
# superseded the old outer handler's `raise` anyway
# since `errors` is populated (below) before any await.
except BaseException as _scope_err:
an._scope_error = _scope_err
errors[actor.aid.uid] = _scope_err
# If we error in the root but the debugger is
# engaged we don't want to prematurely kill (and
@ -689,12 +695,12 @@ async def _open_and_supervise_one_cancels_all_nursery(
# block here might not complete? For now,
# shield both.
with trio.CancelScope(shield=True):
etype: type = type(inner_err)
etype: type = type(_scope_err)
if etype in (
trio.Cancelled,
KeyboardInterrupt,
) or (
is_multi_cancelled(inner_err)
is_multi_cancelled(_scope_err)
):
log.cancel(
f'Actor-nursery cancelled by {etype}\n\n'
@ -711,7 +717,7 @@ async def _open_and_supervise_one_cancels_all_nursery(
log.cancel(
'Actor-nursery caught remote cancellation\n'
'\n'
f'{inner_err.tb_str}'
f'{_scope_err.tb_str}'
)
else:
log.exception(
@ -760,42 +766,6 @@ async def _open_and_supervise_one_cancels_all_nursery(
ria_children=ria_children,
)
# Safety-net handler for anything escaping the inner
# `except BaseException` above (e.g. a `trio.Cancelled`
# during its non-shielded debugger-wait, or a failure
# inside the shielded teardown itself). Post-#477 the
# 2ndary `._ria_nursery` (and its dedicated handler) is
# gone; this now guards the single daemon nursery scope.
# TODO: can this be merged into the inner handler now that
# there's only one nursery? (higher-risk, own PR)
except (
Exception,
BaseExceptionGroup,
trio.Cancelled
) as _outer_err:
outer_err = _outer_err
an._scope_error = outer_err or inner_err
# XXX: yet another guard before allowing the cancel
# sequence in case a (single) child is in debug.
await debug.maybe_wait_for_debugger(
child_in_debug=an._at_least_one_child_in_debug
)
# If actor-local error was raised while waiting on
# ".run_in_actor()" actors then we also want to cancel all
# remaining sub-actors (due to our lone strategy:
# one-cancels-all).
if an._children:
log.cancel(
'Actor-nursery cancelling due error type:\n'
f'{outer_err}\n'
)
with trio.CancelScope(shield=True):
await an.cancel()
raise
finally:
# No errors were raised while awaiting ".run_in_actor()"
# actors but those actors may have returned remote errors as