diff options
author | Thomas Grainger <tagrain@gmail.com> | 2024-10-14 22:45:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-14 22:45:58 (GMT) |
commit | 0b28ea4a35dc7c68c97127f7aad8f0175d77c520 (patch) | |
tree | 17d084f9ece3e282b1d745eadfd395bcfc6024c8 /Lib/asyncio | |
parent | 1bffd7a2a738506a4ad50c6c3c2c32926cce6d14 (diff) | |
download | cpython-0b28ea4a35dc7c68c97127f7aad8f0175d77c520.zip cpython-0b28ea4a35dc7c68c97127f7aad8f0175d77c520.tar.gz cpython-0b28ea4a35dc7c68c97127f7aad8f0175d77c520.tar.bz2 |
gh-124958: Revert "gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles ... (#125486)
* Revert "gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (#12… (#125476)"
This reverts commit e99650b80ace3893c2a80b3f2a4aca99cb305191.
* fix incompatability with gh-124392
Diffstat (limited to 'Lib/asyncio')
-rw-r--r-- | Lib/asyncio/futures.py | 6 | ||||
-rw-r--r-- | Lib/asyncio/taskgroups.py | 41 |
2 files changed, 34 insertions, 13 deletions
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 5f6fa23..c95fce0 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -190,8 +190,7 @@ class Future: the future is done and has an exception set, this exception is raised. """ if self._state == _CANCELLED: - exc = self._make_cancelled_error() - raise exc + raise self._make_cancelled_error() if self._state != _FINISHED: raise exceptions.InvalidStateError('Result is not ready.') self.__log_traceback = False @@ -208,8 +207,7 @@ class Future: InvalidStateError. """ if self._state == _CANCELLED: - exc = self._make_cancelled_error() - raise exc + raise self._make_cancelled_error() if self._state != _FINISHED: raise exceptions.InvalidStateError('Exception is not set.') self.__log_traceback = False diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index f2ee964..9fa772c 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -66,6 +66,20 @@ class TaskGroup: return self async def __aexit__(self, et, exc, tb): + tb = None + try: + return await self._aexit(et, exc) + finally: + # Exceptions are heavy objects that can have object + # cycles (bad for GC); let's not keep a reference to + # a bunch of them. It would be nicer to use a try/finally + # in __aexit__ directly but that introduced some diff noise + self._parent_task = None + self._errors = None + self._base_error = None + exc = None + + async def _aexit(self, et, exc): self._exiting = True if (exc is not None and @@ -122,7 +136,10 @@ class TaskGroup: assert not self._tasks if self._base_error is not None: - raise self._base_error + try: + raise self._base_error + finally: + exc = None if self._parent_cancel_requested: # If this flag is set we *must* call uncancel(). @@ -133,8 +150,14 @@ class TaskGroup: # Propagate CancelledError if there is one, except if there # are other errors -- those have priority. - if propagate_cancellation_error is not None and not self._errors: - raise propagate_cancellation_error + try: + if propagate_cancellation_error is not None and not self._errors: + try: + raise propagate_cancellation_error + finally: + exc = None + finally: + propagate_cancellation_error = None if et is not None and not issubclass(et, exceptions.CancelledError): self._errors.append(exc) @@ -146,14 +169,14 @@ class TaskGroup: if self._parent_task.cancelling(): self._parent_task.uncancel() self._parent_task.cancel() - # Exceptions are heavy objects that can have object - # cycles (bad for GC); let's not keep a reference to - # a bunch of them. try: - me = BaseExceptionGroup('unhandled errors in a TaskGroup', self._errors) - raise me from None + raise BaseExceptionGroup( + 'unhandled errors in a TaskGroup', + self._errors, + ) from None finally: - self._errors = None + exc = None + def create_task(self, coro, *, name=None, context=None): """Create a new task in this group and return it. |