mirror of https://github.com/python/cpython
gh-121621: Disable asyncio freelist in free-threaded build (#122046)
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).
This commit is contained in:
parent
e059aa6b01
commit
97248204a1
|
@ -138,8 +138,10 @@ typedef struct {
|
|||
/* Counter for autogenerated Task names */
|
||||
uint64_t task_name_counter;
|
||||
|
||||
#ifndef Py_GIL_DISABLED
|
||||
futureiterobject *fi_freelist;
|
||||
Py_ssize_t fi_freelist_len;
|
||||
#endif
|
||||
|
||||
/* Linked-list of all tasks which are instances of asyncio.Task or subclasses
|
||||
of it. Third party tasks implementations which don't inherit from
|
||||
|
@ -1579,14 +1581,14 @@ FutureIter_dealloc(futureiterobject *it)
|
|||
|
||||
assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
|
||||
|
||||
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
|
||||
asyncio_state *state = NULL;
|
||||
|
||||
PyObject_GC_UnTrack(it);
|
||||
tp->tp_clear((PyObject *)it);
|
||||
|
||||
#ifndef Py_GIL_DISABLED
|
||||
// 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.
|
||||
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
|
||||
asyncio_state *state = NULL;
|
||||
if (module && _PyModule_GetDef(module) == &_asynciomodule) {
|
||||
state = get_asyncio_state(module);
|
||||
}
|
||||
|
@ -1597,7 +1599,9 @@ FutureIter_dealloc(futureiterobject *it)
|
|||
it->future = (FutureObj*) state->fi_freelist;
|
||||
state->fi_freelist = it;
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
{
|
||||
PyObject_GC_Del(it);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
@ -1801,6 +1805,7 @@ future_new_iter(PyObject *fut)
|
|||
asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
|
||||
ENSURE_FUTURE_ALIVE(state, fut)
|
||||
|
||||
#ifndef Py_GIL_DISABLED
|
||||
if (state->fi_freelist_len) {
|
||||
state->fi_freelist_len--;
|
||||
it = state->fi_freelist;
|
||||
|
@ -1808,7 +1813,9 @@ future_new_iter(PyObject *fut)
|
|||
it->future = NULL;
|
||||
_Py_NewReference((PyObject*) it);
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
{
|
||||
it = PyObject_GC_New(futureiterobject, state->FutureIterType);
|
||||
if (it == NULL) {
|
||||
return NULL;
|
||||
|
@ -3679,6 +3686,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
|
|||
static void
|
||||
module_free_freelists(asyncio_state *state)
|
||||
{
|
||||
#ifndef Py_GIL_DISABLED
|
||||
PyObject *next;
|
||||
PyObject *current;
|
||||
|
||||
|
@ -3693,6 +3701,7 @@ module_free_freelists(asyncio_state *state)
|
|||
}
|
||||
assert(state->fi_freelist_len == 0);
|
||||
state->fi_freelist = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -3723,6 +3732,7 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
|
|||
|
||||
Py_VISIT(state->context_kwname);
|
||||
|
||||
#ifndef Py_GIL_DISABLED
|
||||
// Visit freelist.
|
||||
PyObject *next = (PyObject*) state->fi_freelist;
|
||||
while (next != NULL) {
|
||||
|
@ -3730,6 +3740,8 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
|
|||
Py_VISIT(current);
|
||||
next = (PyObject*) ((futureiterobject*) current)->future;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue