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 spew when event loop exception handler is invoked after loop closure #139

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions newsfragments/134.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix an issue where a call to ``TrioEventLoop.call_exception_handler()`` after
the loop was closed would attempt to call a method on ``None``. This pattern
can be encountered if an ``aiohttp`` session is garbage-collected without being
properly closed, for example.
9 changes: 9 additions & 0 deletions tests/test_trio_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ async def test_get_running_loop():
assert asyncio.get_running_loop() == loop


@pytest.mark.trio
async def test_exception_after_closed(caplog):
async with trio_asyncio.open_loop() as loop:
pass
loop.call_exception_handler({"message": "Test exception after loop closed"})
assert len(caplog.records) == 1
assert caplog.records[0].message == "Test exception after loop closed"


@pytest.mark.trio
async def test_tasks_get_cancelled():
record = []
Expand Down
7 changes: 7 additions & 0 deletions trio_asyncio/_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ def default_exception_handler(self, context):
# Call the original default handler so we get the full info in the log
super().default_exception_handler(context)

if self._nursery is None:
# Event loop is already closed; don't do anything further.
# Some asyncio libraries call the asyncio exception handler
# from their __del__ methods, e.g., aiohttp for "Unclosed
# client session".
return

# Also raise an exception so it can't go unnoticed
exception = context.get("exception")
if exception is None:
Expand Down
Loading