Skip to content

Commit 3aaed08

Browse files
GH-120974: make _asyncio.all_tasks thread safe (#122801)
Make `_asyncio.all_tasks` thread safe, also changes state lock to use critical section.
1 parent 363374c commit 3aaed08

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

Modules/_asynciomodule.c

+15-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#endif
44

55
#include "Python.h"
6+
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION_MUT()
67
#include "pycore_dict.h" // _PyDict_GetItem_KnownHash()
78
#include "pycore_freelist.h" // _Py_FREELIST_POP()
89
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
@@ -77,8 +78,8 @@ typedef struct {
7778
#define Task_Check(state, obj) PyObject_TypeCheck(obj, state->TaskType)
7879

7980
#ifdef Py_GIL_DISABLED
80-
# define ASYNCIO_STATE_LOCK(state) PyMutex_Lock(&state->mutex)
81-
# define ASYNCIO_STATE_UNLOCK(state) PyMutex_Unlock(&state->mutex)
81+
# define ASYNCIO_STATE_LOCK(state) Py_BEGIN_CRITICAL_SECTION_MUT(&state->mutex)
82+
# define ASYNCIO_STATE_UNLOCK(state) Py_END_CRITICAL_SECTION()
8283
#else
8384
# define ASYNCIO_STATE_LOCK(state) ((void)state)
8485
# define ASYNCIO_STATE_UNLOCK(state) ((void)state)
@@ -1923,15 +1924,15 @@ register_task(asyncio_state *state, TaskObj *task)
19231924
assert(task != &state->asyncio_tasks.tail);
19241925
if (task->next != NULL) {
19251926
// already registered
1926-
ASYNCIO_STATE_UNLOCK(state);
1927-
return;
1927+
goto exit;
19281928
}
19291929
assert(task->prev == NULL);
19301930
assert(state->asyncio_tasks.head != NULL);
19311931

19321932
task->next = state->asyncio_tasks.head;
19331933
state->asyncio_tasks.head->prev = task;
19341934
state->asyncio_tasks.head = task;
1935+
exit:
19351936
ASYNCIO_STATE_UNLOCK(state);
19361937
}
19371938

@@ -1951,8 +1952,7 @@ unregister_task(asyncio_state *state, TaskObj *task)
19511952
// not registered
19521953
assert(task->prev == NULL);
19531954
assert(state->asyncio_tasks.head != task);
1954-
ASYNCIO_STATE_UNLOCK(state);
1955-
return;
1955+
goto exit;
19561956
}
19571957
task->next->prev = task->prev;
19581958
if (task->prev == NULL) {
@@ -1964,6 +1964,7 @@ unregister_task(asyncio_state *state, TaskObj *task)
19641964
task->next = NULL;
19651965
task->prev = NULL;
19661966
assert(state->asyncio_tasks.head != task);
1967+
exit:
19671968
ASYNCIO_STATE_UNLOCK(state);
19681969
}
19691970

@@ -3628,6 +3629,8 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
36283629
Py_DECREF(item);
36293630
}
36303631
Py_DECREF(eager_iter);
3632+
int err = 0;
3633+
ASYNCIO_STATE_LOCK(state);
36313634
TaskObj *head = state->asyncio_tasks.head;
36323635
Py_INCREF(head);
36333636
assert(head != NULL);
@@ -3639,11 +3642,16 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
36393642
Py_DECREF(tasks);
36403643
Py_DECREF(loop);
36413644
Py_DECREF(head);
3642-
return NULL;
3645+
err = 1;
3646+
break;
36433647
}
36443648
Py_INCREF(head->next);
36453649
Py_SETREF(head, head->next);
36463650
}
3651+
ASYNCIO_STATE_UNLOCK(state);
3652+
if (err) {
3653+
return NULL;
3654+
}
36473655
PyObject *scheduled_iter = PyObject_GetIter(state->non_asyncio_tasks);
36483656
if (scheduled_iter == NULL) {
36493657
Py_DECREF(tasks);

0 commit comments

Comments
 (0)