]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-126083: Fix a reference leak in `asyncio.Task` when reinitializing with...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 31 Oct 2024 08:19:56 +0000 (09:19 +0100)
committerGitHub <noreply@github.com>
Thu, 31 Oct 2024 08:19:56 +0000 (08:19 +0000)
gh-126083: Fix a reference leak in `asyncio.Task` when reinitializing with new non-`None` context (GH-126103)
(cherry picked from commit d07dcce6935364cab807e0df931ed09b088ade69)

Co-authored-by: Nico-Posada <102486290+Nico-Posada@users.noreply.github.com>
Lib/test/test_asyncio/test_tasks.py
Misc/NEWS.d/next/Library/2024-10-28-22-35-22.gh-issue-126083.TuI--n.rst [new file with mode: 0644]
Modules/_asynciomodule.c

index 6e8a51ce2555d55f4cf76161ddb58a24c8362be9..792ab4fbede0a27c3ada5f473416c4403f8dc2e1 100644 (file)
@@ -2489,6 +2489,28 @@ class BaseTaskTests:
         finally:
             loop.close()
 
+    def test_proper_refcounts(self):
+        # see: https://github.com/python/cpython/issues/126083
+        class Break:
+            def __str__(self):
+                raise RuntimeError("break")
+
+        obj = object()
+        initial_refcount = sys.getrefcount(obj)
+
+        coro = coroutine_function()
+        loop = asyncio.new_event_loop()
+        task = asyncio.Task.__new__(asyncio.Task)
+
+        for _ in range(5):
+            with self.assertRaisesRegex(RuntimeError, 'break'):
+                task.__init__(coro, loop=loop, context=obj, name=Break())
+
+        coro.close()
+        del task
+
+        self.assertEqual(sys.getrefcount(obj), initial_refcount)
+
 
 def add_subclass_tests(cls):
     BaseTask = cls.Task
diff --git a/Misc/NEWS.d/next/Library/2024-10-28-22-35-22.gh-issue-126083.TuI--n.rst b/Misc/NEWS.d/next/Library/2024-10-28-22-35-22.gh-issue-126083.TuI--n.rst
new file mode 100644 (file)
index 0000000..d64b7dd
--- /dev/null
@@ -0,0 +1 @@
+Fixed a reference leak in :class:`asyncio.Task` objects when reinitializing the same object with a non-``None`` context. Patch by Nico Posada.
index 9016c077e0d657b6b4a6cb0b7613ae87edf18078..96821762c5ae681a16d957028d6f0d824e6bb769 100644 (file)
@@ -2143,7 +2143,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
             return -1;
         }
     } else {
-        self->task_context = Py_NewRef(context);
+        Py_XSETREF(self->task_context, Py_NewRef(context));
     }
 
     Py_CLEAR(self->task_fut_waiter);