pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/b5e6fb39a246bf7ee470d58632cdf588bb9d0298

097560d244c08.css" /> gh-120974: Make asyncio `swap_current_task` safe in free-threaded bui… · python/cpython@b5e6fb3 · GitHub
Skip to content

Commit b5e6fb3

Browse files
authored
gh-120974: Make asyncio swap_current_task safe in free-threaded build (#122317)
* gh-120974: Make asyncio `swap_current_task` safe in free-threaded build
1 parent fb864c7 commit b5e6fb3

File tree

3 files changed

+67
-31
lines changed

3 files changed

+67
-31
lines changed

Include/internal/pycore_dict.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,13 @@ PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObjec
108108
/* Consumes references to key and value */
109109
PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);
110110
extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value);
111-
extern int _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result);
111+
// Export for '_asyncio' shared extension
112+
PyAPI_FUNC(int) _PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key,
113+
PyObject *value, Py_hash_t hash);
114+
// Export for '_asyncio' shared extension
115+
PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash_LockHeld(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result);
112116
extern int _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result);
117+
extern int _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result);
113118
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value);
114119

115120
extern int _PyDict_Pop_KnownHash(

Modules/_asynciomodule.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,6 +2026,24 @@ leave_task(asyncio_state *state, PyObject *loop, PyObject *task)
20262026
return res;
20272027
}
20282028

2029+
static PyObject *
2030+
swap_current_task_lock_held(PyDictObject *current_tasks, PyObject *loop,
2031+
Py_hash_t hash, PyObject *task)
2032+
{
2033+
PyObject *prev_task;
2034+
if (_PyDict_GetItemRef_KnownHash_LockHeld(current_tasks, loop, hash, &prev_task) < 0) {
2035+
return NULL;
2036+
}
2037+
if (_PyDict_SetItem_KnownHash_LockHeld(current_tasks, loop, task, hash) < 0) {
2038+
Py_XDECREF(prev_task);
2039+
return NULL;
2040+
}
2041+
if (prev_task == NULL) {
2042+
Py_RETURN_NONE;
2043+
}
2044+
return prev_task;
2045+
}
2046+
20292047
static PyObject *
20302048
swap_current_task(asyncio_state *state, PyObject *loop, PyObject *task)
20312049
{
@@ -2041,24 +2059,15 @@ swap_current_task(asyncio_state *state, PyObject *loop, PyObject *task)
20412059
return prev_task;
20422060
}
20432061

2044-
Py_hash_t hash;
2045-
hash = PyObject_Hash(loop);
2062+
Py_hash_t hash = PyObject_Hash(loop);
20462063
if (hash == -1) {
20472064
return NULL;
20482065
}
2049-
prev_task = _PyDict_GetItem_KnownHash(state->current_tasks, loop, hash);
2050-
if (prev_task == NULL) {
2051-
if (PyErr_Occurred()) {
2052-
return NULL;
2053-
}
2054-
prev_task = Py_None;
2055-
}
2056-
Py_INCREF(prev_task);
2057-
if (_PyDict_SetItem_KnownHash(state->current_tasks, loop, task, hash) == -1) {
2058-
Py_DECREF(prev_task);
2059-
return NULL;
2060-
}
20612066

2067+
PyDictObject *current_tasks = (PyDictObject *)state->current_tasks;
2068+
Py_BEGIN_CRITICAL_SECTION(current_tasks);
2069+
prev_task = swap_current_task_lock_held(current_tasks, loop, hash, task);
2070+
Py_END_CRITICAL_SECTION();
20622071
return prev_task;
20632072
}
20642073

Objects/dictobject.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,6 +2216,29 @@ _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
22162216
return value; // borrowed reference
22172217
}
22182218

2219+
/* Gets an item and provides a new reference if the value is present.
2220+
* Returns 1 if the key is present, 0 if the key is missing, and -1 if an
2221+
* exception occurred.
2222+
*/
2223+
int
2224+
_PyDict_GetItemRef_KnownHash_LockHeld(PyDictObject *op, PyObject *key,
2225+
Py_hash_t hash, PyObject **result)
2226+
{
2227+
PyObject *value;
2228+
Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2229+
assert(ix >= 0 || value == NULL);
2230+
if (ix == DKIX_ERROR) {
2231+
*result = NULL;
2232+
return -1;
2233+
}
2234+
if (value == NULL) {
2235+
*result = NULL;
2236+
return 0; // missing key
2237+
}
2238+
*result = Py_NewRef(value);
2239+
return 1; // key is present
2240+
}
2241+
22192242
/* Gets an item and provides a new reference if the value is present.
22202243
* Returns 1 if the key is present, 0 if the key is missing, and -1 if an
22212244
* exception occurred.
@@ -2460,33 +2483,32 @@ setitem_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
24602483

24612484

24622485
int
2463-
_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
2464-
Py_hash_t hash)
2486+
_PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value,
2487+
Py_hash_t hash)
24652488
{
2466-
PyDictObject *mp;
2489+
PyInterpreterState *interp = _PyInterpreterState_GET();
2490+
if (mp->ma_keys == Py_EMPTY_KEYS) {
2491+
return insert_to_emptydict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
2492+
}
2493+
/* insertdict() handles any resizing that might be necessary */
2494+
return insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
2495+
}
24672496

2497+
int
2498+
_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
2499+
Py_hash_t hash)
2500+
{
24682501
if (!PyDict_Check(op)) {
24692502
PyErr_BadInternalCall();
24702503
return -1;
24712504
}
24722505
assert(key);
24732506
assert(value);
24742507
assert(hash != -1);
2475-
mp = (PyDictObject *)op;
24762508

24772509
int res;
2478-
PyInterpreterState *interp = _PyInterpreterState_GET();
2479-
2480-
Py_BEGIN_CRITICAL_SECTION(mp);
2481-
2482-
if (mp->ma_keys == Py_EMPTY_KEYS) {
2483-
res = insert_to_emptydict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
2484-
}
2485-
else {
2486-
/* insertdict() handles any resizing that might be necessary */
2487-
res = insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
2488-
}
2489-
2510+
Py_BEGIN_CRITICAL_SECTION(op);
2511+
res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)op, key, value, hash);
24902512
Py_END_CRITICAL_SECTION();
24912513
return res;
24922514
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy