gh-143939: Fix assignment to `_PyThreadStateImpl.generator_return_kin… · python/cpython@43bb630

GitHub

File tree

Lib/test

Misc/NEWS.d/next/Core_and_Builtins

Objects

Python

Original file line numberDiff line numberDiff line change@@ -2265,6 +2265,20 @@ def c():

22652265# before fixing, visible stack from throw would be shorter than from send.

22662266self.assertEqual(len_send, len_throw)

226722672268+deftest_call_generator_in_frame_clear(self):

2269+# gh-143939: Running a generator while clearing the coroutine's frame

2270+# should not be misinterpreted as a yield.

2271+classCallGeneratorOnDealloc:

2272+def__del__(self):

2273+next(xforxin [1])

2274+2275+asyncdefcoro():

2276+obj=CallGeneratorOnDealloc()

2277+return42

2278+2279+yielded, result=run_async(coro())

2280+self.assertEqual(yielded, [])

2281+self.assertEqual(result, 42)

[email protected](

22702284support.is_emscriptenorsupport.is_wasi,

Original file line numberDiff line numberDiff line change@@ -0,0 +1,3 @@

1+Fix erroneous "cannot reuse already awaited coroutine" error that could

2+occur when a generator was run during the process of clearing a coroutine's

3+frame.

Original file line numberDiff line numberDiff line change@@ -280,6 +280,9 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, int exc)

280280281281if (return_kind==GENERATOR_YIELD) {

282282assert(result!=NULL&& !_PyErr_Occurred(tstate));

283+#ifndefPy_GIL_DISABLED

284+assert(FRAME_STATE_SUSPENDED(gen->gi_frame_state));

285+#endif

283286*presult=result;

284287returnPYGEN_NEXT;

285288 }

Original file line numberDiff line numberDiff line change@@ -1914,14 +1914,16 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)

19141914assert(frame->owner==FRAME_OWNED_BY_GENERATOR);

19151915PyGenObject*gen=_PyGen_GetGeneratorFromFrame(frame);

19161916FT_ATOMIC_STORE_INT8_RELEASE(gen->gi_frame_state, FRAME_CLEARED);

1917- ((_PyThreadStateImpl*)tstate)->generator_return_kind=GENERATOR_RETURN;

19181917assert(tstate->exc_info==&gen->gi_exc_state);

19191918tstate->exc_info=gen->gi_exc_state.previous_item;

19201919gen->gi_exc_state.previous_item=NULL;

19211920assert(frame->frame_obj==NULL||frame->frame_obj->f_frame==frame);

19221921frame->previous=NULL;

19231922_PyFrame_ClearExceptCode(frame);

19241923_PyErr_ClearExcState(&gen->gi_exc_state);

1924+// gh-143939: There must not be any escaping calls between setting

1925+// the generator return kind and returning from _PyEval_EvalFrame.

1926+ ((_PyThreadStateImpl*)tstate)->generator_return_kind=GENERATOR_RETURN;

19251927}

1926192819271929void