8000 [3.13] gh-126083: Fix a reference leak in `asyncio.Task` when reiniti… · python/cpython@ac00bf0 · GitHub
[go: up one dir, main page]

Skip to content

Commit ac00bf0

Browse files
[3.13] gh-126083: Fix a reference leak in asyncio.Task when reinitializing with new non-None context (GH-126103) (#126229)
gh-126083: Fix a reference leak in `asyncio.Task` when reinitializing with new non-`None` context (GH-126103) (cherry picked from commit d07dcce) Co-authored-by: Nico-Posada <102486290+Nico-Posada@users.noreply.github.com>
1 parent 57668a4 commit ac00bf0

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

Lib/test/test_asyncio/test_tasks.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2684,6 +2684,28 @@ def test_get_context(self):
26842684
finally:
26852685
loop.close()
26862686

2687+
def test_proper_refcounts(self):
2688+
# see: https://github.com/python/cpython/issues/126083
2689+
class Break:
2690+
def __str__(self):
2691+
raise RuntimeError("break")
2692+
2693+
obj = object()
2694+
initial_refcount = sys.getrefcount(obj)
2695+
2696+
coro = coroutine_function()
2697+
loop = asyncio.new_event_loop()
2698+
task = asyncio.Task.__new__(asyncio.Task)
2699+
2700+
for _ in range(5):
2701+
with self.assertRaisesRegex(RuntimeError, 'break'):
2702+
task.__init__(coro, loop=loop, context=obj, name=Break())
2703+
2704+
coro.close()
2705+
del task
2706+
2707+
self.assertEqual(sys.getrefcount(obj), initial_refcount)
2708+
26872709

26882710
def add_subclass_tests(cls):
26892711
BaseTask = cls.Task
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a reference leak in :class:`asyncio.Task` objects when reinitializing the same object with a non-``None`` context. Patch by Nico Posada.

Modules/_asynciomodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2070,7 +2070,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
20702070
return -1;
20712071
}
20722072
} else {
2073-
self->task_context = Py_NewRef(context);
2073+
Py_XSETREF(self->task_context, Py_NewRef(context));
20742074
}
20752075

20762076
Py_CLEAR(self->task_fut_waiter);

0 commit comments

Comments
 (0)
0