Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion Lib/test/test_asyncio/test_eager_task_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from asyncio import tasks
from test.test_asyncio import utils as test_utils
from test.test_asyncio.test_tasks import get_innermost_context
from test import support
from test.support.script_helper import assert_python_ok

MOCK_ANY = mock.ANY

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

def test_issue105987(self):
code = """if 1:
from _asyncio import _swap_current_task

class DummyTask:
pass

class DummyLoop:
pass

l = DummyLoop()
_swap_current_task(l, DummyTask())
t = _swap_current_task(l, None)
"""

_, out, err = assert_python_ok("-c", code)
self.assertFalse(err)

class AsyncTaskCounter:
def __init__(self, loop, *, task_class, eager):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix crash due to improper reference counting in :mod:`asyncio` eager task factory internal routines.
11 changes: 7 additions & 4 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2047,20 +2047,23 @@ swap_current_task(asyncio_state *state, PyObject *loop, PyObject *task)
}
prev_task = Py_None;
}
Py_INCREF(prev_task);

if (task == Py_None) {
if (_PyDict_DelItem_KnownHash(state->current_tasks, loop, hash) == -1) {
return NULL;
goto error;
}
} else {
if (_PyDict_SetItem_KnownHash(state->current_tasks, loop, task, hash) == -1) {
return NULL;
goto error;
}
}

Py_INCREF(prev_task);

return prev_task;

error:
Py_DECREF(prev_task);
return NULL;
}

/* ----- Task */
Expand Down