-
-
Notifications
You must be signed in to change notification settings - Fork 367
Open
Description
There are a few places where we want to crash trio.run
with a given exception. Meaning something like: cancel the main task, unwind everything, raise the given exception as the final result. This is needed for:
KeyboardInterrupt
(when it's not delivered directly to a task) (Rethink KeyboardInterrupt protection APIs #733, Raise deferred KeyboardInterrupt out of run() after cancelling all tasks #1537, etc.)- Exceptions from "can't fail" functions like
run_sync_soon
and system tasks (which also want a way to avoid raisingTrioInternalError
– Make the TrioInternalError experience less confusing #1056) - When a deadlock is detected (Global deadlock detector #1085)
- When pytest-trio's test timeout expires (Add test timeout support pytest-trio#53)
It's not quite clear what the semantics should be though!
One option: when asked to "crash", we:
- cancel the main task, if it's still running (if not, that means we're already shutting down, so we can skip this step)
- save the "crash" exception in the
Runner
state somewhere - on the way out of
run
, check if we have any saved exceptions, and if so, do... something with them. Ifmain_task_outcome
is aValue
, it's easy, just raise aMultiError(saved_exceptions)
. If themain_task_outcome
is anError
, I'm not sure what the best approach is.MultiError(saved_exceptions)
with themain_task_outcome
as__context__
? That could be confusing since the exception stored inmain_task_outcome
might have only occurred after and as a result of a sequence like "crash" → cancel main task → something on the cancel path raises an exception. I guess the only alternatives though are (a) discarding the main task exception, (b)MultiError(saved_exceptions + [main_task_exception])
. Not sure if either of those is actually better.
Note that we're already doing something kinda similar at the end of unrolled_run
to handle ki_pending
.