gh-120974: Make _asyncio._enter_task atomic in the free-threaded build (#122138)

Use `PyDict_SetDefaultRef` to set the current task in a single operation
under the dictionary's lock.
This commit is contained in:
Sam Gross 2024-07-23 04:47:14 -04:00 committed by GitHub
parent a9bb3c7b3b
commit 47847aa8ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 5 additions and 10 deletions

View File

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