Skip to content

Commit

Permalink
gh-126083: Fix a reference leak in asyncio.Task when reinitializing…
Browse files Browse the repository at this point in the history
… with new non-`None` context (#126103)
  • Loading branch information
Nico-Posada authored Oct 31, 2024
1 parent d467d92 commit d07dcce
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
22 changes: 22 additions & 0 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d07dcce

Please sign in to comment.