Skip to content

gh-111085: Fix invalid state handling in TaskGroup and Timeout #111111

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

Conversation

serhiy-storchaka
Copy link
Member

@serhiy-storchaka serhiy-storchaka commented Oct 20, 2023

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError if they are improperly used.

  • When they are used without entering the context manager.
  • When they are used after finishing.
  • When the context manager is entered more than once (simultaneously or sequentially).
  • If there is no current task when entering the context manager.

They are now left in consistent state after raising an exception, so following operations can be correctly performed (if they are allowed).

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They are now left in consistent state after raising an exception, so
following operations can be correctly performed (if they are allowed).

Co-authored-by: James Hilton-Balfe <[email protected]>
@AlexWaygood AlexWaygood changed the title gh-110910: Fix invalid state handling in TaskGroup and Timeout gh-111085: Fix invalid state handling in TaskGroup and Timeout Oct 20, 2023
Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

Thanks for doing this! The original code was adapted from various sources...

@@ -82,11 +81,14 @@ def __repr__(self) -> str:
return f"<Timeout [{self._state.value}]{info_str}>"

async def __aenter__(self) -> "Timeout":
if self._state is not _State.CREATED:
raise RuntimeError(f"Timeout has been already {self._state.value}")
Copy link
Member

Choose a reason for hiding this comment

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

Looking at the list of states, this produces crooked grammar in several cases (active, expiring). Maybe "Timeout cannot be entered in state X"? Or look at the error in reschedule() for inspiration.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you, I did not know that "already active" and "already expiring" are not valid. In TaskGroup it is simply "has been already entered" but I decided to enhance it. Technically, "already entered" should be enough.

reschedule() also produces weird message ("Cannot change state of created Timeout"). How can you change state of not created Timeout?

try:
for _ in coro.__await__():
pass
except:
Copy link
Member

Choose a reason for hiding this comment

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

Maybe except BaseException as err: nonlocal exc; exc = err ?

@@ -82,7 +82,7 @@ def __repr__(self) -> str:

async def __aenter__(self) -> "Timeout":
if self._state is not _State.CREATED:
raise RuntimeError(f"Timeout has been already {self._state.value}")
raise RuntimeError("Timeout has been already entered")
Copy link
Member

Choose a reason for hiding this comment

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

Sorry, English grammar is hard. It should be "has already been entered".

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

Bingo!

@serhiy-storchaka
Copy link
Member Author

Thank you for your review Guido.

@serhiy-storchaka serhiy-storchaka merged commit 6c23635 into python:main Oct 21, 2023
@miss-islington-app
Copy link

Thanks @serhiy-storchaka for the PR 🌮🎉.. I'm working now to backport this PR to: 3.11, 3.12.
🐍🍒⛏🤖

@serhiy-storchaka serhiy-storchaka deleted the asyncio-taskgroups-timeouts-states branch October 21, 2023 19:18
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Oct 21, 2023
…ythonGH-111111)

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They now remain in a consistent state after an exception is thrown,
so subsequent operations can be performed correctly (if they are allowed).

(cherry picked from commit 6c23635)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: James Hilton-Balfe <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Oct 21, 2023
…ythonGH-111111)

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They now remain in a consistent state after an exception is thrown,
so subsequent operations can be performed correctly (if they are allowed).

(cherry picked from commit 6c23635)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: James Hilton-Balfe <[email protected]>
@bedevere-app
Copy link

bedevere-app bot commented Oct 21, 2023

GH-111171 is a backport of this pull request to the 3.12 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.12 only security fixes label Oct 21, 2023
@bedevere-app
Copy link

bedevere-app bot commented Oct 21, 2023

GH-111172 is a backport of this pull request to the 3.11 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.11 only security fixes label Oct 21, 2023
serhiy-storchaka added a commit that referenced this pull request Oct 21, 2023
…GH-111111) (GH-111172)

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They now remain in a consistent state after an exception is thrown,
so subsequent operations can be performed correctly (if they are allowed).

(cherry picked from commit 6c23635)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: James Hilton-Balfe <[email protected]>
serhiy-storchaka added a commit that referenced this pull request Oct 21, 2023
…GH-111111) (GH-111171)

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They now remain in a consistent state after an exception is thrown,
so subsequent operations can be performed correctly (if they are allowed).

(cherry picked from commit 6c23635)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: James Hilton-Balfe <[email protected]>
aisk pushed a commit to aisk/cpython that referenced this pull request Feb 11, 2024
…ython#111111)

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They now remain in a consistent state after an exception is thrown,
so subsequent operations can be performed correctly (if they are allowed).

Co-authored-by: James Hilton-Balfe <[email protected]>
Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
…ython#111111)

asyncio.TaskGroup and asyncio.Timeout classes now raise proper RuntimeError
if they are improperly used.

* When they are used without entering the context manager.
* When they are used after finishing.
* When the context manager is entered more than once (simultaneously or
  sequentially).
* If there is no current task when entering the context manager.

They now remain in a consistent state after an exception is thrown,
so subsequent operations can be performed correctly (if they are allowed).

Co-authored-by: James Hilton-Balfe <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants