Skip to content

Commit d2cbb6e

Browse files
authored
gh-105987: Fix reference counting issue in _asyncio._swap_current_task (#105989)
1 parent 4849a80 commit d2cbb6e

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

Lib/test/test_asyncio/test_eager_task_factory.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from unittest import mock
88
from asyncio import tasks
99
from test.test_asyncio import utils as test_utils
10+
import test.support
11+
from test.support.script_helper import assert_python_ok
1012

1113
MOCK_ANY = mock.ANY
1214

@@ -222,6 +224,23 @@ class PyEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase
222224
class CEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase):
223225
Task = getattr(tasks, '_CTask', None)
224226

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

226245
class AsyncTaskCounter:
227246
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)