Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Old way: - exceptions and regular returns from main were captured, then re-raised/returned from init, then captured again, then re-raised/returned from run() - exceptions in system tasks were converted into TrioInternalErrors (one-at-a-time, using MultiError.filter()), except for a whitelist of types (Cancelled, KeyboardInterrupt, GeneratorExit, TrioInternalError), and then re-raised in the init task. - exceptions in the run loop machinery were caught in run(), and converted into TrioInternalErrors (if they weren't already). New way: - exceptions and regular returns from main are captured, and then re-raised/returned from run() directly - exceptions in system tasks are allowed to propagate naturally into the init task - exceptions in the init task are re-raised out of the run loop machinery - exceptions in the run loop machinery are caught in run(), and converted into TrioInternalErrors (if they aren't already). This needs one new special case to detect when spawning the main task itself errors, and treating that as a regular non-TrioInternalError, but otherwise it simplifies things a lot. And, it removes 2 unnecessary traceback frames from every trio traceback. Removing the special case handling for some exception types in system tasks did break a few tests. It's not as bad as it seems though: - Cancelled was allowed through so it could reach the system nursery's __aexit__; that still happens. But now if it's not caught there, it gets converted into TrioInternalError instead of being allowed to escape from trio.run(). - KeyboardInterrupt should never happen in system tasks anyway; not sure why we had a special case to allow this. - GeneratorExit should never happen; if it does, it's probably because things blew up real good, and then the system task coroutine got GC'ed, and called coro.close(). In this case letting it escape is the right thing to do; coro.close() will catch it. In other cases, letting it escape and get converted into a TrioInternalError is fine. - Letting TrioInternalError through works the same as before. Also, if multiple system tasks crash, we now get a single TrioInternalError with the original MultiError as a __cause__, rather than a MultiError containing multiple TrioInternalErrors. This is probably less confusing, and it's more compatible with the python-triogh-611 approach to things.
- Loading branch information