From 82235449b85165add62c1b200299456a50a1d097 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Wed, 26 Jun 2024 10:41:32 +0530 Subject: gh-107803: fix thread safety issue in double linked list implementation (#121007) --- Include/internal/pycore_object.h | 4 ++-- Modules/_asynciomodule.c | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 311f295..ebb0f30 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -126,8 +126,8 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n) } #define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n) -extern void _Py_SetImmortal(PyObject *op); -extern void _Py_SetImmortalUntracked(PyObject *op); +PyAPI_FUNC(void) _Py_SetImmortal(PyObject *op); +PyAPI_FUNC(void) _Py_SetImmortalUntracked(PyObject *op); // Makes an immortal object mortal again with the specified refcnt. Should only // be used during runtime finalization. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 4672fc7..87ad236 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -6,6 +6,7 @@ #include "pycore_dict.h" // _PyDict_GetItem_KnownHash() #include "pycore_modsupport.h" // _PyArg_CheckPositional() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_object.h" // _Py_SetImmortalUntracked #include "pycore_pyerrors.h" // _PyErr_ClearExcState() #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_pystate.h" // _PyThreadState_GET() @@ -3706,6 +3707,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) } Py_DECREF(eager_iter); TaskObj *head = state->asyncio_tasks.head; + Py_INCREF(head); assert(head != NULL); assert(head->prev == NULL); TaskObj *tail = &state->asyncio_tasks.tail; @@ -3714,10 +3716,11 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) if (add_one_task(state, tasks, (PyObject *)head, loop) < 0) { Py_DECREF(tasks); Py_DECREF(loop); + Py_DECREF(head); return NULL; } - head = head->next; - assert(head != NULL); + Py_INCREF(head->next); + Py_SETREF(head, head->next); } PyObject *scheduled_iter = PyObject_GetIter(state->non_asyncio_tasks); if (scheduled_iter == NULL) { @@ -3944,6 +3947,8 @@ static int module_exec(PyObject *mod) { asyncio_state *state = get_asyncio_state(mod); + Py_SET_TYPE(&state->asyncio_tasks.tail, state->TaskType); + _Py_SetImmortalUntracked((PyObject *)&state->asyncio_tasks.tail); state->asyncio_tasks.head = &state->asyncio_tasks.tail; #define CREATE_TYPE(m, tp, spec, base) \ -- cgit v0.12