summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKumar Aditya <kumaraditya@python.org>2024-08-11 15:19:31 (GMT)
committerGitHub <noreply@github.com>2024-08-11 15:19:31 (GMT)
commit3aaed083a3f5eb7e490495c460b3dc1ce7451ce8 (patch)
treee23f6588f50341d3dc1e14c204a277e7c0bdb39b
parent363374cf69a7e2292fe3f1c6bedd199088958cc2 (diff)
downloadcpython-3aaed083a3f5eb7e490495c460b3dc1ce7451ce8.zip
cpython-3aaed083a3f5eb7e490495c460b3dc1ce7451ce8.tar.gz
cpython-3aaed083a3f5eb7e490495c460b3dc1ce7451ce8.tar.bz2
GH-120974: make `_asyncio.all_tasks` thread safe (#122801)
Make `_asyncio.all_tasks` thread safe, also changes state lock to use critical section.
-rw-r--r--Modules/_asynciomodule.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index c6eb43f..0a769c4 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()
@@ -77,8 +78,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()
#else
# define ASYNCIO_STATE_LOCK(state) ((void)state)
# define ASYNCIO_STATE_UNLOCK(state) ((void)state)
@@ -1923,8 +1924,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 +1932,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 +1952,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 +1964,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);
}
@@ -3628,6 +3629,8 @@ _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);
assert(head != NULL);
@@ -3639,11 +3642,16 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
Py_DECREF(tasks);
Py_DECREF(loop);
Py_DECREF(head);
- return NULL;
+ 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);