mirror of
https://github.com/python/cpython.git
synced 2026-02-19 22:01:14 +00:00
gh-120321: Make gi_frame_state transitions atomic in FT build (gh-142599)
This makes generator frame state transitions atomic in the free threading build, which avoids segfaults when trying to execute a generator from multiple threads concurrently. There are still a few operations that aren't thread-safe and may crash if performed concurrently on the same generator/coroutine: * Accessing gi_yieldfrom/cr_await/ag_await * Accessing gi_frame/cr_frame/ag_frame * Async generator operations
This commit is contained in:
parent
e2a7db7175
commit
08bc03ff2a
16 changed files with 1124 additions and 883 deletions
|
|
@ -2304,7 +2304,8 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
|
|||
{
|
||||
assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
|
||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||
gen->gi_frame_state = FRAME_CLEARED;
|
||||
FT_ATOMIC_STORE_INT8_RELEASE(gen->gi_frame_state, FRAME_CLEARED);
|
||||
((_PyThreadStateImpl *)tstate)->generator_return_kind = GENERATOR_RETURN;
|
||||
assert(tstate->exc_info == &gen->gi_exc_state);
|
||||
tstate->exc_info = gen->gi_exc_state.previous_item;
|
||||
gen->gi_exc_state.previous_item = NULL;
|
||||
|
|
@ -3979,15 +3980,13 @@ _PyEval_GetAwaitable(PyObject *iterable, int oparg)
|
|||
Py_TYPE(iterable), oparg);
|
||||
}
|
||||
else if (PyCoro_CheckExact(iter)) {
|
||||
PyObject *yf = _PyGen_yf((PyGenObject*)iter);
|
||||
if (yf != NULL) {
|
||||
/* `iter` is a coroutine object that is being
|
||||
awaited, `yf` is a pointer to the current awaitable
|
||||
being awaited on. */
|
||||
Py_DECREF(yf);
|
||||
PyCoroObject *coro = (PyCoroObject *)iter;
|
||||
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(coro->cr_frame_state);
|
||||
if (frame_state == FRAME_SUSPENDED_YIELD_FROM) {
|
||||
/* `iter` is a coroutine object that is being awaited. */
|
||||
Py_CLEAR(iter);
|
||||
_PyErr_SetString(PyThreadState_GET(), PyExc_RuntimeError,
|
||||
"coroutine is being awaited already");
|
||||
"coroutine is being awaited already");
|
||||
}
|
||||
}
|
||||
return iter;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue