https://github.com/python/cpython/commit/d07dcce6935364cab807e0df931ed09b088ade69
commit: d07dcce6935364cab807e0df931ed09b088ade69
branch: main
author: Nico-Posada <[email protected]>
committer: sobolevn <[email protected]>
date: 2024-10-31T10:47:57+03:00
summary:

gh-126083: Fix a reference leak in `asyncio.Task` when reinitializing with new 
non-`None` context (#126103)

files:
A Misc/NEWS.d/next/Library/2024-10-28-22-35-22.gh-issue-126083.TuI--n.rst
M Lib/test/test_asyncio/test_tasks.py
M Modules/_asynciomodule.c

diff --git a/Lib/test/test_asyncio/test_tasks.py 
b/Lib/test/test_asyncio/test_tasks.py
index a1013ab803348d..9d2d356631b42c 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -2688,6 +2688,28 @@ def test_get_context(self):
         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
index 00000000000000..d64b7dd2fedbd6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-10-28-22-35-22.gh-issue-126083.TuI--n.rst
@@ -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.
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index d4135f04e56575..c2500fbd692d4d 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -2120,7 +2120,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);

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to