There was an error while loading. Please reload this page.
asyncio.all_tasks
1 parent b725297 commit 7dc41adCopy full SHA for 7dc41ad
2 files changed
Include/internal/pycore_object.h
@@ -120,7 +120,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
120
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
121
122
extern void _Py_AddRefTotal(PyThreadState *, Py_ssize_t);
123
-extern void _Py_IncRefTotal(PyThreadState *);
+extern PyAPI_FUNC(void) _Py_IncRefTotal(PyThreadState *);
124
extern void _Py_DecRefTotal(PyThreadState *);
125
126
# define _Py_DEC_REFTOTAL(interp) \
Modules/_asynciomodule.c
@@ -3772,11 +3772,20 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
3772
3773
llist_for_each_safe(node, &state->asyncio_tasks_head) {
3774
TaskObj *task = llist_data(node, TaskObj, task_node);
3775
- if (PyList_Append(tasks, (PyObject *)task) < 0) {
3776
- Py_DECREF(tasks);
3777
- Py_DECREF(loop);
3778
- err = 1;
3779
- 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
3780
+ // if it is concurrently getting deallocated in another thread,
3781
+ // otherwise it gets added to the list.
3782
+ if (_Py_TryIncref((PyObject *)task)) {
3783
+ if (_PyList_AppendTakeRef((PyListObject *)tasks, (PyObject *)task) < 0) {
3784
+ Py_DECREF(tasks);
3785
+ Py_DECREF(loop);
3786
+ err = 1;
3787
+ break;
3788
+ }
3789
}
3790
3791
ASYNCIO_STATE_UNLOCK(state);
0 commit comments