mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
[3.13] gh-121621: Disable asyncio freelist in free-threaded build (GH-122046) (#122048)
The futureobj freelist isn't thread-safe. We intend to re-enable the
freelist in a thread-safe way for 3.14 (but not 3.13).
(cherry picked from commit 97248204a1
)
This commit is contained in:
parent
bf7f4f357b
commit
f3c79cb400
1 changed files with 17 additions and 5 deletions
|
@ -71,8 +71,10 @@ typedef struct {
|
||||||
/* Counter for autogenerated Task names */
|
/* Counter for autogenerated Task names */
|
||||||
uint64_t task_name_counter;
|
uint64_t task_name_counter;
|
||||||
|
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
futureiterobject *fi_freelist;
|
futureiterobject *fi_freelist;
|
||||||
Py_ssize_t fi_freelist_len;
|
Py_ssize_t fi_freelist_len;
|
||||||
|
#endif
|
||||||
} asyncio_state;
|
} asyncio_state;
|
||||||
|
|
||||||
static inline asyncio_state *
|
static inline asyncio_state *
|
||||||
|
@ -1520,14 +1522,14 @@ FutureIter_dealloc(futureiterobject *it)
|
||||||
|
|
||||||
assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
|
assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
|
||||||
|
|
||||||
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
|
|
||||||
asyncio_state *state = NULL;
|
|
||||||
|
|
||||||
PyObject_GC_UnTrack(it);
|
PyObject_GC_UnTrack(it);
|
||||||
tp->tp_clear((PyObject *)it);
|
tp->tp_clear((PyObject *)it);
|
||||||
|
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
// GH-115874: We can't use PyType_GetModuleByDef here as the type might have
|
// GH-115874: We can't use PyType_GetModuleByDef here as the type might have
|
||||||
// already been cleared, which is also why we must check if ht_module != NULL.
|
// already been cleared, which is also why we must check if ht_module != NULL.
|
||||||
|
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
|
||||||
|
asyncio_state *state = NULL;
|
||||||
if (module && _PyModule_GetDef(module) == &_asynciomodule) {
|
if (module && _PyModule_GetDef(module) == &_asynciomodule) {
|
||||||
state = get_asyncio_state(module);
|
state = get_asyncio_state(module);
|
||||||
}
|
}
|
||||||
|
@ -1538,7 +1540,9 @@ FutureIter_dealloc(futureiterobject *it)
|
||||||
it->future = (FutureObj*) state->fi_freelist;
|
it->future = (FutureObj*) state->fi_freelist;
|
||||||
state->fi_freelist = it;
|
state->fi_freelist = it;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
PyObject_GC_Del(it);
|
PyObject_GC_Del(it);
|
||||||
Py_DECREF(tp);
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
@ -1742,6 +1746,7 @@ future_new_iter(PyObject *fut)
|
||||||
asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
|
asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
|
||||||
ENSURE_FUTURE_ALIVE(state, fut)
|
ENSURE_FUTURE_ALIVE(state, fut)
|
||||||
|
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
if (state->fi_freelist_len) {
|
if (state->fi_freelist_len) {
|
||||||
state->fi_freelist_len--;
|
state->fi_freelist_len--;
|
||||||
it = state->fi_freelist;
|
it = state->fi_freelist;
|
||||||
|
@ -1749,7 +1754,9 @@ future_new_iter(PyObject *fut)
|
||||||
it->future = NULL;
|
it->future = NULL;
|
||||||
_Py_NewReference((PyObject*) it);
|
_Py_NewReference((PyObject*) it);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
it = PyObject_GC_New(futureiterobject, state->FutureIterType);
|
it = PyObject_GC_New(futureiterobject, state->FutureIterType);
|
||||||
if (it == NULL) {
|
if (it == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3463,6 +3470,7 @@ _asyncio_current_task_impl(PyObject *module, PyObject *loop)
|
||||||
static void
|
static void
|
||||||
module_free_freelists(asyncio_state *state)
|
module_free_freelists(asyncio_state *state)
|
||||||
{
|
{
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
PyObject *next;
|
PyObject *next;
|
||||||
PyObject *current;
|
PyObject *current;
|
||||||
|
|
||||||
|
@ -3477,6 +3485,7 @@ module_free_freelists(asyncio_state *state)
|
||||||
}
|
}
|
||||||
assert(state->fi_freelist_len == 0);
|
assert(state->fi_freelist_len == 0);
|
||||||
state->fi_freelist = NULL;
|
state->fi_freelist = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -3507,6 +3516,7 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
|
||||||
|
|
||||||
Py_VISIT(state->context_kwname);
|
Py_VISIT(state->context_kwname);
|
||||||
|
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
// Visit freelist.
|
// Visit freelist.
|
||||||
PyObject *next = (PyObject*) state->fi_freelist;
|
PyObject *next = (PyObject*) state->fi_freelist;
|
||||||
while (next != NULL) {
|
while (next != NULL) {
|
||||||
|
@ -3514,6 +3524,8 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
|
||||||
Py_VISIT(current);
|
Py_VISIT(current);
|
||||||
next = (PyObject*) ((futureiterobject*) current)->future;
|
next = (PyObject*) ((futureiterobject*) current)->future;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue