]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-120974: Make _asyncio._enter_task atomic in the free-threaded build (#122138)
authorSam Gross <colesbury@gmail.com>
Tue, 23 Jul 2024 08:47:14 +0000 (04:47 -0400)
committerGitHub <noreply@github.com>
Tue, 23 Jul 2024 08:47:14 +0000 (14:17 +0530)
Use `PyDict_SetDefaultRef` to set the current task in a single operation
under the dictionary's lock.

Modules/_asynciomodule.c

index 372f19794be0dd3c9f3fbdbd7ee34081c0f23d95..dd64b233e90e602515d1361c4d529a32272adc21 100644 (file)
@@ -2009,14 +2009,11 @@ static int
 enter_task(asyncio_state *state, PyObject *loop, PyObject *task)
 {
     PyObject *item;
-    Py_hash_t hash;
-    hash = PyObject_Hash(loop);
-    if (hash == -1) {
+    int res = PyDict_SetDefaultRef(state->current_tasks, loop, task, &item);
+    if (res < 0) {
         return -1;
     }
-    item = _PyDict_GetItem_KnownHash(state->current_tasks, loop, hash);
-    if (item != NULL) {
-        Py_INCREF(item);
+    else if (res == 1) {
         PyErr_Format(
             PyExc_RuntimeError,
             "Cannot enter into task %R while another " \
@@ -2025,10 +2022,8 @@ enter_task(asyncio_state *state, PyObject *loop, PyObject *task)
         Py_DECREF(item);
         return -1;
     }
-    if (PyErr_Occurred()) {
-        return -1;
-    }
-    return _PyDict_SetItem_KnownHash(state->current_tasks, loop, task, hash);
+    Py_DECREF(item);
+    return 0;
 }