diff --git a/CHANGES/6807.bugfix.rst b/CHANGES/6807.bugfix.rst new file mode 100644 index 00000000000..4eb07b9e0da --- /dev/null +++ b/CHANGES/6807.bugfix.rst @@ -0,0 +1 @@ +Stopped logging exceptions from ``web.run_app()`` that would be raised regardless -- by :user:`Dreamsorcerer`. diff --git a/aiohttp/web.py b/aiohttp/web.py index b56560d733e..650fe3417d0 100644 --- a/aiohttp/web.py +++ b/aiohttp/web.py @@ -6,6 +6,7 @@ import warnings from argparse import ArgumentParser from collections.abc import Iterable +from contextlib import suppress from importlib import import_module from typing import ( Any, @@ -501,11 +502,15 @@ def run_app( except (GracefulExit, KeyboardInterrupt): # pragma: no cover pass finally: - _cancel_tasks({main_task}, loop) - _cancel_tasks(asyncio.all_tasks(loop), loop) - loop.run_until_complete(loop.shutdown_asyncgens()) - loop.close() - asyncio.set_event_loop(None) + try: + main_task.cancel() + with suppress(asyncio.CancelledError): + loop.run_until_complete(main_task) + finally: + _cancel_tasks(asyncio.all_tasks(loop), loop) + loop.run_until_complete(loop.shutdown_asyncgens()) + loop.close() + asyncio.set_event_loop(None) def main(argv: List[str]) -> None: diff --git a/tests/test_run_app.py b/tests/test_run_app.py index 4a94099f2d5..3fa8dc11303 100644 --- a/tests/test_run_app.py +++ b/tests/test_run_app.py @@ -979,6 +979,23 @@ async def init() -> web.Application: assert count == 3 +def test_run_app_raises_exception(patched_loop: asyncio.AbstractEventLoop) -> None: + async def context(app: web.Application) -> AsyncIterator[None]: + raise RuntimeError("foo") + yield # pragma: no cover + + app = web.Application() + app.cleanup_ctx.append(context) + + with mock.patch.object( + patched_loop, "call_exception_handler", autospec=True, spec_set=True + ) as m: + with pytest.raises(RuntimeError, match="foo"): + web.run_app(app, loop=patched_loop) + + assert not m.called + + class TestShutdown: def raiser(self) -> NoReturn: raise KeyboardInterrupt