Skip to content

Commit 9e6f8d4

Browse files
[3.12] gh-105987: Fix reference counting issue in `_asyncio._swap_cur… (#106099)
[3.12] gh-105987: Fix reference counting issue in `_asyncio._swap_current_task` (GH-105989). (cherry picked from commit d2cbb6e) Co-authored-by: chgnrdv <[email protected]>
1 parent 8418964 commit 9e6f8d4

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

Lib/test/test_asyncio/test_eager_task_factory.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from asyncio import tasks
1313
from test.test_asyncio import utils as test_utils
1414
from test.test_asyncio.test_tasks import get_innermost_context
15-
from test import support
15+
from test.support.script_helper import assert_python_ok
1616

1717
MOCK_ANY = mock.ANY
1818

@@ -228,6 +228,23 @@ class PyEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase
228228
class CEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase):
229229
Task = getattr(tasks, '_CTask', None)
230230

231+
def test_issue105987(self):
232+
code = """if 1:
233+
from _asyncio import _swap_current_task
234+
235+
class DummyTask:
236+
pass
237+
238+
class DummyLoop:
239+
pass
240+
241+
l = DummyLoop()
242+
_swap_current_task(l, DummyTask())
243+
t = _swap_current_task(l, None)
244+
"""
245+
246+
_, out, err = assert_python_ok("-c", code)
247+
self.assertFalse(err)
231248

232249
class AsyncTaskCounter:
233250
def __init__(self, loop, *, task_class, eager):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix crash due to improper reference counting in :mod:`asyncio` eager task factory internal routines.

Modules/_asynciomodule.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,20 +2047,23 @@ swap_current_task(asyncio_state *state, PyObject *loop, PyObject *task)
20472047
}
20482048
prev_task = Py_None;
20492049
}
2050+
Py_INCREF(prev_task);
20502051

20512052
if (task == Py_None) {
20522053
if (_PyDict_DelItem_KnownHash(state->current_tasks, loop, hash) == -1) {
2053-
return NULL;
2054+
goto error;
20542055
}
20552056
} else {
20562057
if (_PyDict_SetItem_KnownHash(state->current_tasks, loop, task, hash) == -1) {
2057-
return NULL;
2058+
goto error;
20582059
}
20592060
}
20602061

2061-
Py_INCREF(prev_task);
2062-
20632062
return prev_task;
2063+
2064+
error:
2065+
Py_DECREF(prev_task);
2066+
return NULL;
20642067
}
20652068

20662069
/* ----- Task */

0 commit comments

Comments
 (0)