Skip to content

Commit f3c79cb

Browse files
authored
[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 9724820)
1 parent bf7f4f3 commit f3c79cb

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

Modules/_asynciomodule.c

+17-5
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@ typedef struct {
7171
/* Counter for autogenerated Task names */
7272
uint64_t task_name_counter;
7373

74+
#ifndef Py_GIL_DISABLED
7475
futureiterobject *fi_freelist;
7576
Py_ssize_t fi_freelist_len;
77+
#endif
7678
} asyncio_state;
7779

7880
static inline asyncio_state *
@@ -1520,14 +1522,14 @@ FutureIter_dealloc(futureiterobject *it)
15201522

15211523
assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
15221524

1523-
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
1524-
asyncio_state *state = NULL;
1525-
15261525
PyObject_GC_UnTrack(it);
15271526
tp->tp_clear((PyObject *)it);
15281527

1528+
#ifndef Py_GIL_DISABLED
15291529
// GH-115874: We can't use PyType_GetModuleByDef here as the type might have
15301530
// already been cleared, which is also why we must check if ht_module != NULL.
1531+
PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
1532+
asyncio_state *state = NULL;
15311533
if (module && _PyModule_GetDef(module) == &_asynciomodule) {
15321534
state = get_asyncio_state(module);
15331535
}
@@ -1538,7 +1540,9 @@ FutureIter_dealloc(futureiterobject *it)
15381540
it->future = (FutureObj*) state->fi_freelist;
15391541
state->fi_freelist = it;
15401542
}
1541-
else {
1543+
else
1544+
#endif
1545+
{
15421546
PyObject_GC_Del(it);
15431547
Py_DECREF(tp);
15441548
}
@@ -1742,14 +1746,17 @@ future_new_iter(PyObject *fut)
17421746
asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
17431747
ENSURE_FUTURE_ALIVE(state, fut)
17441748

1749+
#ifndef Py_GIL_DISABLED
17451750
if (state->fi_freelist_len) {
17461751
state->fi_freelist_len--;
17471752
it = state->fi_freelist;
17481753
state->fi_freelist = (futureiterobject*) it->future;
17491754
it->future = NULL;
17501755
_Py_NewReference((PyObject*) it);
17511756
}
1752-
else {
1757+
else
1758+
#endif
1759+
{
17531760
it = PyObject_GC_New(futureiterobject, state->FutureIterType);
17541761
if (it == NULL) {
17551762
return NULL;
@@ -3463,6 +3470,7 @@ _asyncio_current_task_impl(PyObject *module, PyObject *loop)
34633470
static void
34643471
module_free_freelists(asyncio_state *state)
34653472
{
3473+
#ifndef Py_GIL_DISABLED
34663474
PyObject *next;
34673475
PyObject *current;
34683476

@@ -3477,6 +3485,7 @@ module_free_freelists(asyncio_state *state)
34773485
}
34783486
assert(state->fi_freelist_len == 0);
34793487
state->fi_freelist = NULL;
3488+
#endif
34803489
}
34813490

34823491
static int
@@ -3507,13 +3516,16 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
35073516

35083517
Py_VISIT(state->context_kwname);
35093518

3519+
#ifndef Py_GIL_DISABLED
35103520
// Visit freelist.
35113521
PyObject *next = (PyObject*) state->fi_freelist;
35123522
while (next != NULL) {
35133523
PyObject *current = next;
35143524
Py_VISIT(current);
35153525
next = (PyObject*) ((futureiterobject*) current)->future;
35163526
}
3527+
#endif
3528+
35173529
return 0;
35183530
}
35193531

0 commit comments

Comments
 (0)