mirror of
https://github.com/python/cpython.git
synced 2025-11-25 12:44:13 +00:00
gh-128002: fix asyncio.all_tasks against concurrent deallocations of tasks (#128541)
This commit is contained in:
parent
b725297cee
commit
7dc41ad6a7
2 changed files with 15 additions and 6 deletions
|
|
@ -120,7 +120,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
|
|||
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
|
||||
|
||||
extern void _Py_AddRefTotal(PyThreadState *, Py_ssize_t);
|
||||
extern void _Py_IncRefTotal(PyThreadState *);
|
||||
extern PyAPI_FUNC(void) _Py_IncRefTotal(PyThreadState *);
|
||||
extern void _Py_DecRefTotal(PyThreadState *);
|
||||
|
||||
# define _Py_DEC_REFTOTAL(interp) \
|
||||
|
|
|
|||
|
|
@ -3772,11 +3772,20 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
|
|||
|
||||
llist_for_each_safe(node, &state->asyncio_tasks_head) {
|
||||
TaskObj *task = llist_data(node, TaskObj, task_node);
|
||||
if (PyList_Append(tasks, (PyObject *)task) < 0) {
|
||||
Py_DECREF(tasks);
|
||||
Py_DECREF(loop);
|
||||
err = 1;
|
||||
break;
|
||||
// The linked list holds borrowed references to task
|
||||
// as such it is possible that the task is concurrently
|
||||
// deallocated while added to this list.
|
||||
// To protect against concurrent deallocations,
|
||||
// we first try to incref the task which would fail
|
||||
// if it is concurrently getting deallocated in another thread,
|
||||
// otherwise it gets added to the list.
|
||||
if (_Py_TryIncref((PyObject *)task)) {
|
||||
if (_PyList_AppendTakeRef((PyListObject *)tasks, (PyObject *)task) < 0) {
|
||||
Py_DECREF(tasks);
|
||||
Py_DECREF(loop);
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ASYNCIO_STATE_UNLOCK(state);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue