Skip to content

Commit 9724820

Browse files
authored
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).
1 parent e059aa6 commit 9724820

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

Modules/_asynciomodule.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,10 @@ typedef struct {
138138
/* Counter for autogenerated Task names */
139139
uint64_t task_name_counter;
140140

141+
#ifndef Py_GIL_DISABLED
141142
futureiterobject *fi_freelist;
142143
Py_ssize_t fi_freelist_len;
144+
#endif
143145

144146
/* Linked-list of all tasks which are instances of asyncio.Task or subclasses
145147
of it. Third party tasks implementations which don't inherit from
@@ -1579,14 +1581,14 @@ FutureIter_dealloc(futureiterobject *it)
15791581

15801582
assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
15811583

1582-
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
1583-
asyncio_state *state = NULL;
1584-
15851584
PyObject_GC_UnTrack(it);
15861585
tp->tp_clear((PyObject *)it);
15871586

1587+
#ifndef Py_GIL_DISABLED
15881588
// GH-115874: We can't use PyType_GetModuleByDef here as the type might have
15891589
// already been cleared, which is also why we must check if ht_module != NULL.
1590+
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
1591+
asyncio_state *state = NULL;
15901592
if (module && _PyModule_GetDef(module) == &_asynciomodule) {
15911593
state = get_asyncio_state(module);
15921594
}
@@ -1597,7 +1599,9 @@ FutureIter_dealloc(futureiterobject *it)
15971599
it->future = (FutureObj*) state->fi_freelist;
15981600
state->fi_freelist = it;
15991601
}
1600-
else {
1602+
else
1603+
#endif
1604+
{
16011605
PyObject_GC_Del(it);
16021606
Py_DECREF(tp);
16031607
}
@@ -1801,14 +1805,17 @@ future_new_iter(PyObject *fut)
18011805
asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
18021806
ENSURE_FUTURE_ALIVE(state, fut)
18031807

1808+
#ifndef Py_GIL_DISABLED
18041809
if (state->fi_freelist_len) {
18051810
state->fi_freelist_len--;
18061811
it = state->fi_freelist;
18071812
state->fi_freelist = (futureiterobject*) it->future;
18081813
it->future = NULL;
18091814
_Py_NewReference((PyObject*) it);
18101815
}
1811-
else {
1816+
else
1817+
#endif
1818+
{
18121819
it = PyObject_GC_New(futureiterobject, state->FutureIterType);
18131820
if (it == NULL) {
18141821
return NULL;
@@ -3679,6 +3686,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
36793686
static void
36803687
module_free_freelists(asyncio_state *state)
36813688
{
3689+
#ifndef Py_GIL_DISABLED
36823690
PyObject *next;
36833691
PyObject *current;
36843692

@@ -3693,6 +3701,7 @@ module_free_freelists(asyncio_state *state)
36933701
}
36943702
assert(state->fi_freelist_len == 0);
36953703
state->fi_freelist = NULL;
3704+
#endif
36963705
}
36973706

36983707
static int
@@ -3723,13 +3732,16 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
37233732

37243733
Py_VISIT(state->context_kwname);
37253734

3735+
#ifndef Py_GIL_DISABLED
37263736
// Visit freelist.
37273737
PyObject *next = (PyObject*) state->fi_freelist;
37283738
while (next != NULL) {
37293739
PyObject *current = next;
37303740
Py_VISIT(current);
37313741
next = (PyObject*) ((futureiterobject*) current)->future;
37323742
}
3743+
#endif
3744+
37333745
return 0;
37343746
}
37353747

0 commit comments

Comments
 (0)