Skip to content

Commit 5f00501

Browse files
gh-130221: fix crash when accessing module state while interp is finalizing in asyncio (#130245)
1 parent 660f126 commit 5f00501

File tree

1 file changed

+9
-13
lines changed

1 file changed

+9
-13
lines changed

Modules/_asynciomodule.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ static PyObject * future_new_iter(PyObject *);
216216

217217
static PyObject *
218218
task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *result);
219-
219+
static void unregister_task(TaskObj *task);
220220

221221
static void
222222
clear_task_coro(TaskObj *task)
@@ -409,7 +409,6 @@ future_ensure_alive(FutureObj *fut)
409409
} \
410410
} while(0);
411411

412-
static void unregister_task(asyncio_state *state, TaskObj *task);
413412

414413
static int
415414
future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
@@ -422,7 +421,7 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
422421
// remove task from linked-list of tasks
423422
// as it is finished now
424423
TaskObj *task = (TaskObj *)fut;
425-
unregister_task(state, task);
424+
unregister_task(task);
426425
}
427426

428427
if (fut->fut_callback0 != NULL) {
@@ -2169,9 +2168,8 @@ static PyMethodDef TaskWakeupDef = {
21692168
/* ----- Task introspection helpers */
21702169

21712170
static void
2172-
register_task(asyncio_state *state, TaskObj *task)
2171+
register_task(TaskObj *task)
21732172
{
2174-
assert(Task_Check(state, task));
21752173
if (task->task_node.next != NULL) {
21762174
// already registered
21772175
assert(task->task_node.prev != NULL);
@@ -2200,9 +2198,8 @@ unregister_task_safe(TaskObj *task)
22002198
}
22012199

22022200
static void
2203-
unregister_task(asyncio_state *state, TaskObj *task)
2201+
unregister_task(TaskObj *task)
22042202
{
2205-
assert(Task_Check(state, task));
22062203
#ifdef Py_GIL_DISABLED
22072204
// check if we are in the same thread
22082205
// if so, we can avoid locking
@@ -2396,7 +2393,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
23962393
// works correctly in non-owning threads.
23972394
_PyObject_SetMaybeWeakref((PyObject *)self);
23982395
#endif
2399-
register_task(state, self);
2396+
register_task(self);
24002397
return 0;
24012398
}
24022399

@@ -2981,8 +2978,7 @@ TaskObj_dealloc(PyObject *self)
29812978
_PyObject_ResurrectStart(self);
29822979
// Unregister the task here so that even if any subclass of Task
29832980
// which doesn't end up calling TaskObj_finalize not crashes.
2984-
asyncio_state *state = get_asyncio_state_by_def(self);
2985-
unregister_task(state, task);
2981+
unregister_task(task);
29862982

29872983
PyObject_CallFinalizer(self);
29882984

@@ -3519,7 +3515,7 @@ task_eager_start(asyncio_state *state, TaskObj *task)
35193515
}
35203516

35213517
if (task->task_state == STATE_PENDING) {
3522-
register_task(state, task);
3518+
register_task(task);
35233519
} else {
35243520
// This seems to really help performance on pyperformance benchmarks
35253521
clear_task_coro(task);
@@ -3710,7 +3706,7 @@ _asyncio__register_task_impl(PyObject *module, PyObject *task)
37103706
if (Task_Check(state, task)) {
37113707
// task is an asyncio.Task instance or subclass, use efficient
37123708
// linked-list implementation.
3713-
register_task(state, (TaskObj *)task);
3709+
register_task((TaskObj *)task);
37143710
Py_RETURN_NONE;
37153711
}
37163712
// As task does not inherit from asyncio.Task, fallback to less efficient
@@ -3762,7 +3758,7 @@ _asyncio__unregister_task_impl(PyObject *module, PyObject *task)
37623758
{
37633759
asyncio_state *state = get_asyncio_state(module);
37643760
if (Task_Check(state, task)) {
3765-
unregister_task(state, (TaskObj *)task);
3761+
unregister_task((TaskObj *)task);
37663762
Py_RETURN_NONE;
37673763
}
37683764
PyObject *res = PyObject_CallMethodOneArg(state->non_asyncio_tasks,

0 commit comments

Comments
 (0)