Skip to content

Commit 032fb57

Browse files
Fix CancelledError stopping other cleanup contexts completing (#8908)
1 parent 8a525d9 commit 032fb57

4 files changed

Lines changed: 14 additions & 12 deletions

File tree

CHANGES/8908.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed ``CancelledError`` from one cleanup context stopping other contexts from completing -- by :user:`Dreamsorcerer`.

aiohttp/web_app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ async def _on_cleanup(self, app: Application) -> None:
430430
await it.__anext__()
431431
except StopAsyncIteration:
432432
pass
433-
except Exception as exc:
433+
except (Exception, asyncio.CancelledError) as exc:
434434
errors.append(exc)
435435
else:
436436
errors.append(RuntimeError(f"{it!r} has more than one 'yield'"))

docs/web_advanced.rst

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,13 +1068,10 @@ below::
10681068
async with client.pubsub() as pubsub:
10691069
await pubsub.subscribe(channel)
10701070
while True:
1071-
try:
1072-
msg = await pubsub.get_message(ignore_subscribe_messages=True)
1073-
if msg is not None:
1074-
for ws in app["websockets"]:
1075-
await ws.send_str("{}: {}".format(channel, msg))
1076-
except asyncio.CancelledError:
1077-
break
1071+
msg = await pubsub.get_message(ignore_subscribe_messages=True)
1072+
if msg is not None:
1073+
for ws in app["websockets"]:
1074+
await ws.send_str("{}: {}".format(channel, msg))
10781075

10791076

10801077
async def background_tasks(app):
@@ -1083,7 +1080,8 @@ below::
10831080
yield
10841081

10851082
app[redis_listener].cancel()
1086-
await app[redis_listener]
1083+
with contextlib.suppress(asyncio.CancelledError):
1084+
await app[redis_listener]
10871085

10881086

10891087
app = web.Application()

tests/test_web_app.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import asyncio
2-
from typing import Any, AsyncIterator, Callable, Iterator, NoReturn
2+
from typing import Any, AsyncIterator, Callable, Iterator, NoReturn, Type
33
from unittest import mock
44

55
import pytest
@@ -334,7 +334,10 @@ async def fail_ctx(app: web.Application) -> AsyncIterator[NoReturn]:
334334
assert ctx_state == "CLEAN"
335335

336336

337-
async def test_cleanup_ctx_exception_on_cleanup_multiple() -> None:
337+
@pytest.mark.parametrize("exc_cls", (Exception, asyncio.CancelledError))
338+
async def test_cleanup_ctx_exception_on_cleanup_multiple(
339+
exc_cls: Type[BaseException],
340+
) -> None:
338341
app = web.Application()
339342
out = []
340343

@@ -346,7 +349,7 @@ async def inner(app: web.Application) -> AsyncIterator[None]:
346349
yield None
347350
out.append("post_" + str(num))
348351
if fail:
349-
raise Exception("fail_" + str(num))
352+
raise exc_cls("fail_" + str(num))
350353

351354
return inner
352355

0 commit comments

Comments
 (0)