Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix spurious error when asyncio.run() task raises SystemExit #149

Merged
merged 1 commit into from
Apr 23, 2024

Conversation

oremanj
Copy link
Member

@oremanj oremanj commented Apr 22, 2024

SystemExit passes through the asyncio loop, so the stop() callback scheduled by the main task's Future's completion doesn't run; which then means it's pending when we re-enter the asyncio loop to do cleanup tasks like shutdown_asyncgens. Fix by not enqueueing the stop() callback if we can tell that the exception is going to pass through the asyncio loop.

Relevant upstream issue: https://bugs.python.org/issue22429

@@ -139,6 +139,14 @@ def is_done(_):
nonlocal result

result = outcome.capture(future.result)
if isinstance(result, outcome.Error) and isinstance(
result.error, (SystemExit, KeyboardInterrupt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at the exception hierarchy, do you need to include GeneratorExit here too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; this is trying to match logic in asyncio where specifically these two exceptions will come out of the event loop if raised by a task.

asyncio/tasks.py:

class Task(...):
    ...
    def __step_run_and_handle_result(self, exc):
        coro = self._coro
        try:
            if exc is None:
                # We use the `send` method directly, because coroutines
                # don't have `__iter__` and `__next__` methods.
                result = coro.send(None)
            else:
                result = coro.throw(exc)
        ...
        except (KeyboardInterrupt, SystemExit) as exc:
            super().set_exception(exc)
            raise
        except BaseException as exc:
            super().set_exception(exc)
        else:
            ...

@axiomiety axiomiety merged commit 6f2870a into python-trio:master Apr 23, 2024
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants