[Python-checkins] gh-93297: Make asyncio task groups prevent child tasks from being GCed (GH-93299) (#93305)

1st1 webhook-mailer at python.org
Fri May 27 18:47:03 EDT 2022


https://github.com/python/cpython/commit/cf63b80bc482ef971ecb6d3ed9a1dc4a93d73744
commit: cf63b80bc482ef971ecb6d3ed9a1dc4a93d73744
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: 1st1 <yury at edgedb.com>
date: 2022-05-27T15:46:57-07:00
summary:

gh-93297: Make asyncio task groups prevent child tasks from being GCed (GH-93299) (#93305)

(cherry picked from commit e6a57678cafe18ca132ee9510252168fcc392a8d)

Co-authored-by: Yury Selivanov <yury at edgedb.com>

Co-authored-by: Yury Selivanov <yury at edgedb.com>

files:
A Misc/NEWS.d/next/Library/2022-05-27-13-18-18.gh-issue-93297.e2zuHz.rst
M Lib/asyncio/taskgroups.py

diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index 6af21f3a15d93..9e0610deed281 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -3,8 +3,6 @@
 
 __all__ = ["TaskGroup"]
 
-import weakref
-
 from . import events
 from . import exceptions
 from . import tasks
@@ -19,8 +17,7 @@ def __init__(self):
         self._loop = None
         self._parent_task = None
         self._parent_cancel_requested = False
-        self._tasks = weakref.WeakSet()
-        self._unfinished_tasks = 0
+        self._tasks = set()
         self._errors = []
         self._base_error = None
         self._on_completed_fut = None
@@ -29,8 +26,6 @@ def __repr__(self):
         info = ['']
         if self._tasks:
             info.append(f'tasks={len(self._tasks)}')
-        if self._unfinished_tasks:
-            info.append(f'unfinished={self._unfinished_tasks}')
         if self._errors:
             info.append(f'errors={len(self._errors)}')
         if self._aborting:
@@ -93,7 +88,7 @@ async def __aexit__(self, et, exc, tb):
         # can be cancelled multiple times if our parent task
         # is being cancelled repeatedly (or even once, when
         # our own cancellation is already in progress)
-        while self._unfinished_tasks:
+        while self._tasks:
             if self._on_completed_fut is None:
                 self._on_completed_fut = self._loop.create_future()
 
@@ -114,7 +109,7 @@ async def __aexit__(self, et, exc, tb):
 
             self._on_completed_fut = None
 
-        assert self._unfinished_tasks == 0
+        assert not self._tasks
 
         if self._base_error is not None:
             raise self._base_error
@@ -141,7 +136,7 @@ async def __aexit__(self, et, exc, tb):
     def create_task(self, coro, *, name=None, context=None):
         if not self._entered:
             raise RuntimeError(f"TaskGroup {self!r} has not been entered")
-        if self._exiting and self._unfinished_tasks == 0:
+        if self._exiting and not self._tasks:
             raise RuntimeError(f"TaskGroup {self!r} is finished")
         if context is None:
             task = self._loop.create_task(coro)
@@ -149,7 +144,6 @@ def create_task(self, coro, *, name=None, context=None):
             task = self._loop.create_task(coro, context=context)
         tasks._set_task_name(task, name)
         task.add_done_callback(self._on_task_done)
-        self._unfinished_tasks += 1
         self._tasks.add(task)
         return task
 
@@ -169,10 +163,9 @@ def _abort(self):
                 t.cancel()
 
     def _on_task_done(self, task):
-        self._unfinished_tasks -= 1
-        assert self._unfinished_tasks >= 0
+        self._tasks.discard(task)
 
-        if self._on_completed_fut is not None and not self._unfinished_tasks:
+        if self._on_completed_fut is not None and not self._tasks:
             if not self._on_completed_fut.done():
                 self._on_completed_fut.set_result(True)
 
diff --git a/Misc/NEWS.d/next/Library/2022-05-27-13-18-18.gh-issue-93297.e2zuHz.rst b/Misc/NEWS.d/next/Library/2022-05-27-13-18-18.gh-issue-93297.e2zuHz.rst
new file mode 100644
index 0000000000000..a8e4cd93d3047
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-05-27-13-18-18.gh-issue-93297.e2zuHz.rst
@@ -0,0 +1 @@
+Make asyncio task groups prevent child tasks from being GCed



More information about the Python-checkins mailing list