gh-105987: Fix reference counting issue in `_asyncio._swap_current_task` (#105989)

This commit is contained in:
chgnrdv 2023-06-24 08:23:24 +03:00 committed by GitHub
parent 4849a80dd1
commit d2cbb6e918
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 4 deletions

View File

@ -7,6 +7,8 @@ import unittest
from unittest import mock
from asyncio import tasks
from test.test_asyncio import utils as test_utils
import test.support
from test.support.script_helper import assert_python_ok
MOCK_ANY = mock.ANY
@ -222,6 +224,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):

View File

@ -0,0 +1 @@
Fix crash due to improper reference counting in :mod:`asyncio` eager task factory internal routines.

View File

@ -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 */