-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-102780: Fix uncancel() call in asyncio timeouts #102815
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
Changes from all commits
9f96cea
07517b7
1150db0
d207fb1
912f26d
ee574fc
c91dae7
902691e
0f7bde5
07c40cc
2a8914e
a6f3114
6e299fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,6 +84,7 @@ def __repr__(self) -> str: | |
async def __aenter__(self) -> "Timeout": | ||
self._state = _State.ENTERED | ||
self._task = tasks.current_task() | ||
self._cancelling = self._task.cancelling() | ||
if self._task is None: | ||
raise RuntimeError("Timeout should be used inside a task") | ||
self.reschedule(self._when) | ||
|
@@ -104,10 +105,10 @@ async def __aexit__( | |
if self._state is _State.EXPIRING: | ||
self._state = _State.EXPIRED | ||
|
||
if self._task.uncancel() == 0 and exc_type is exceptions.CancelledError: | ||
# Since there are no outstanding cancel requests, we're | ||
if self._task.uncancel() <= self._cancelling and exc_type is exceptions.CancelledError: | ||
# Since there are no new cancel requests, we're | ||
# handling this. | ||
raise TimeoutError | ||
raise TimeoutError from exc_val | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a nice improvement that maybe ought to be called out in the commit message? (If you agree I can handle that when I merge it.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this done by default? I see the same traceback with and without this on this example: import asyncio
async def func():
await asyncio.sleep(1)
async def main():
async with asyncio.timeout(0.1):
await func()
asyncio.run(main()) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite. When using
(If both are set it follows There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Precicely. I has bothered me for a while that timeouts happen with the latter message, as if somehow, there was an error during exception handling. I wanted to use the opportunity to roll that fix in :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thank you, agreed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ah, right! I missed that. Adding a test would be nice. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add that in a few hours. |
||
elif self._state is _State.ENTERED: | ||
self._state = _State.EXITED | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
The :class:`asyncio.Timeout` context manager now works reliably even when performing cleanup due | ||
to task cancellation. Previously it could raise a | ||
:exc:`~asyncio.CancelledError` instead of an :exc:`~asyncio.TimeoutError` in such cases. |
Uh oh!
There was an error while loading. Please reload this page.