https://github.com/python/cpython/commit/42d2bedb875f42f0580ee2cfb4bd80a5a229bbd4
commit: 42d2bedb875f42f0580ee2cfb4bd80a5a229bbd4
branch: main
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-12-11T15:04:49+05:30
summary:
gh-142556: fix crash when a task gets re-registered during finalization in
`asyncio` (#142565)
files:
A Misc/NEWS.d/next/Library/2025-12-11-09-03-07.gh-issue-142556.RuiBte.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 9809621a324450..a3c5351fed0252 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -3045,6 +3045,26 @@ class BaseTaskIntrospectionTests:
_enter_task = None
_leave_task = None
all_tasks = None
+ Task = None
+
+ def test_register_task_resurrection(self):
+ register_task = self._register_task
+ class EvilLoop:
+ def get_debug(self):
+ return False
+
+ def call_exception_handler(self, context):
+ register_task(context["task"])
+
+ async def coro_fn ():
+ pass
+
+ coro = coro_fn()
+ self.addCleanup(coro.close)
+ loop = EvilLoop()
+ with self.assertRaises(AttributeError):
+ self.Task(coro, loop=loop)
+
def test__register_task_1(self):
class TaskLike:
@@ -3175,6 +3195,7 @@ class PyIntrospectionTests(test_utils.TestCase,
BaseTaskIntrospectionTests):
_leave_task = staticmethod(tasks._py_leave_task)
all_tasks = staticmethod(tasks._py_all_tasks)
current_task = staticmethod(tasks._py_current_task)
+ Task = tasks._PyTask
@unittest.skipUnless(hasattr(tasks, '_c_register_task'),
@@ -3187,10 +3208,12 @@ class CIntrospectionTests(test_utils.TestCase,
BaseTaskIntrospectionTests):
_leave_task = staticmethod(tasks._c_leave_task)
all_tasks = staticmethod(tasks._c_all_tasks)
current_task = staticmethod(tasks._c_current_task)
+ Task = tasks._CTask
else:
_register_task = _unregister_task = _enter_task = _leave_task = None
+
class BaseCurrentLoopTests:
current_task = None
diff --git
a/Misc/NEWS.d/next/Library/2025-12-11-09-03-07.gh-issue-142556.RuiBte.rst
b/Misc/NEWS.d/next/Library/2025-12-11-09-03-07.gh-issue-142556.RuiBte.rst
new file mode 100644
index 00000000000000..782e62b65a36f3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-12-11-09-03-07.gh-issue-142556.RuiBte.rst
@@ -0,0 +1 @@
+Fix crash when a task gets re-registered during finalization in
:mod:`asyncio`. Patch by Kumar Aditya.
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 9b2b7011244d77..0e6a1e93e04f33 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -2990,16 +2990,12 @@ static PyType_Spec Task_spec = {
static void
TaskObj_dealloc(PyObject *self)
{
- _PyObject_ResurrectStart(self);
- // Unregister the task here so that even if any subclass of Task
- // which doesn't end up calling TaskObj_finalize not crashes.
- unregister_task((TaskObj *)self);
-
- PyObject_CallFinalizer(self);
-
- if (_PyObject_ResurrectEnd(self)) {
- return;
+ if (PyObject_CallFinalizerFromDealloc(self) < 0) {
+ return; // resurrected
}
+ // unregister the task after finalization so that
+ // if the task gets resurrected, it remains registered
+ unregister_task((TaskObj *)self);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
_______________________________________________
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]