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

This commit is contained in:
Nico-Posada 2024-10-31 03:47:57 -04:00 committed by GitHub
parent d467d9246c
commit d07dcce693
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 1 deletions

View File

@ -2688,6 +2688,28 @@ class BaseTaskTests:
finally: finally:
loop.close() 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): def add_subclass_tests(cls):
BaseTask = cls.Task BaseTask = cls.Task

View File

@ -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.

View File

@ -2120,7 +2120,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
return -1; return -1;
} }
} else { } else {
self->task_context = Py_NewRef(context); Py_XSETREF(self->task_context, Py_NewRef(context));
} }
Py_CLEAR(self->task_fut_waiter); Py_CLEAR(self->task_fut_waiter);