From f72dc299c432f435e310f7f5afebd868b7ca8617 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Wed, 7 Aug 2024 22:38:39 +0530 Subject: [PATCH 1/3] make _asyncio_all_tasks_impl thread safe --- Modules/_asynciomodule.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index c6eb43f044fdbd..dd2a809a834efc 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -3628,6 +3628,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) Py_DECREF(item); } Py_DECREF(eager_iter); + ASYNCIO_STATE_LOCK(state); TaskObj *head = state->asyncio_tasks.head; Py_INCREF(head); assert(head != NULL); @@ -3636,6 +3637,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) while (head != tail) { if (add_one_task(state, tasks, (PyObject *)head, loop) < 0) { + ASYNCIO_STATE_UNLOCK(state); Py_DECREF(tasks); Py_DECREF(loop); Py_DECREF(head); @@ -3644,6 +3646,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) Py_INCREF(head->next); Py_SETREF(head, head->next); } + ASYNCIO_STATE_UNLOCK(state); PyObject *scheduled_iter = PyObject_GetIter(state->non_asyncio_tasks); if (scheduled_iter == NULL) { Py_DECREF(tasks); From beb012ae571c7dafa76d295d8d3c557111ff2ee4 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 10 Aug 2024 22:24:35 +0530 Subject: [PATCH 2/3] use critical section --- Modules/_asynciomodule.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index dd2a809a834efc..8a8e179795208d 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -77,8 +77,8 @@ typedef struct { #define Task_Check(state, obj) PyObject_TypeCheck(obj, state->TaskType) #ifdef Py_GIL_DISABLED -# define ASYNCIO_STATE_LOCK(state) PyMutex_Lock(&state->mutex) -# define ASYNCIO_STATE_UNLOCK(state) PyMutex_Unlock(&state->mutex) +# define ASYNCIO_STATE_LOCK(state) Py_BEGIN_CRITICAL_SECTION_MUT(&state->mutex) +# define ASYNCIO_STATE_UNLOCK(state) Py_END_CRITICAL_SECTION(&state->mutex) #else # define ASYNCIO_STATE_LOCK(state) ((void)state) # define ASYNCIO_STATE_UNLOCK(state) ((void)state) @@ -1923,8 +1923,7 @@ register_task(asyncio_state *state, TaskObj *task) assert(task != &state->asyncio_tasks.tail); if (task->next != NULL) { // already registered - ASYNCIO_STATE_UNLOCK(state); - return; + goto exit; } assert(task->prev == NULL); assert(state->asyncio_tasks.head != NULL); @@ -1932,6 +1931,7 @@ register_task(asyncio_state *state, TaskObj *task) task->next = state->asyncio_tasks.head; state->asyncio_tasks.head->prev = task; state->asyncio_tasks.head = task; +exit: ASYNCIO_STATE_UNLOCK(state); } @@ -1951,8 +1951,7 @@ unregister_task(asyncio_state *state, TaskObj *task) // not registered assert(task->prev == NULL); assert(state->asyncio_tasks.head != task); - ASYNCIO_STATE_UNLOCK(state); - return; + goto exit; } task->next->prev = task->prev; if (task->prev == NULL) { @@ -1964,6 +1963,7 @@ unregister_task(asyncio_state *state, TaskObj *task) task->next = NULL; task->prev = NULL; assert(state->asyncio_tasks.head != task); +exit: ASYNCIO_STATE_UNLOCK(state); } @@ -3637,11 +3637,10 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) while (head != tail) { if (add_one_task(state, tasks, (PyObject *)head, loop) < 0) { - ASYNCIO_STATE_UNLOCK(state); Py_DECREF(tasks); Py_DECREF(loop); Py_DECREF(head); - return NULL; + goto error; } Py_INCREF(head->next); Py_SETREF(head, head->next); @@ -3666,6 +3665,9 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) Py_DECREF(scheduled_iter); Py_DECREF(loop); return tasks; +error: + ASYNCIO_STATE_UNLOCK(state); + return NULL; } static int From 1d03dd1a545cfe65aa5bb779e14347b5cecc084c Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 10 Aug 2024 22:49:53 +0530 Subject: [PATCH 3/3] fix it --- Modules/_asynciomodule.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 8a8e179795208d..0a769c46b87ac8 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -3,6 +3,7 @@ #endif #include "Python.h" +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION_MUT() #include "pycore_dict.h" // _PyDict_GetItem_KnownHash() #include "pycore_freelist.h" // _Py_FREELIST_POP() #include "pycore_modsupport.h" // _PyArg_CheckPositional() @@ -78,7 +79,7 @@ typedef struct { #ifdef Py_GIL_DISABLED # define ASYNCIO_STATE_LOCK(state) Py_BEGIN_CRITICAL_SECTION_MUT(&state->mutex) -# define ASYNCIO_STATE_UNLOCK(state) Py_END_CRITICAL_SECTION(&state->mutex) +# define ASYNCIO_STATE_UNLOCK(state) Py_END_CRITICAL_SECTION() #else # define ASYNCIO_STATE_LOCK(state) ((void)state) # define ASYNCIO_STATE_UNLOCK(state) ((void)state) @@ -3628,6 +3629,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) Py_DECREF(item); } Py_DECREF(eager_iter); + int err = 0; ASYNCIO_STATE_LOCK(state); TaskObj *head = state->asyncio_tasks.head; Py_INCREF(head); @@ -3640,12 +3642,16 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) Py_DECREF(tasks); Py_DECREF(loop); Py_DECREF(head); - goto error; + err = 1; + break; } Py_INCREF(head->next); Py_SETREF(head, head->next); } ASYNCIO_STATE_UNLOCK(state); + if (err) { + return NULL; + } PyObject *scheduled_iter = PyObject_GetIter(state->non_asyncio_tasks); if (scheduled_iter == NULL) { Py_DECREF(tasks); @@ -3665,9 +3671,6 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop) Py_DECREF(scheduled_iter); Py_DECREF(loop); return tasks; -error: - ASYNCIO_STATE_UNLOCK(state); - return NULL; } static int