diff --git a/Objects/genobject.c b/Objects/genobject.c index e632f43e92a..899c84326d7 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -641,18 +641,15 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, return gen_send_ex(gen, Py_None, 1, 0); goto throw_here; } + + PyThreadState *tstate = _PyThreadState_GET(); + PyFrameObject *f = tstate->frame; + _PyShadowFrame *sf = tstate->shadow_frame; + _PyShadowFrame_PtrKind old_ptr_kind = _PyShadowFrame_GetPtrKind(sf); if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) { /* `yf` is a generator or a coroutine. */ - PyThreadState *tstate = _PyThreadState_GET(); - PyFrameObject *f = tstate->frame; - _PyShadowFrame *sf = tstate->shadow_frame; - _PyShadowFrame_PtrKind old_ptr_kind = _PyShadowFrame_GetPtrKind(sf); - - /* Since we are fast-tracking things by skipping the eval loop, - we need to update the current frame so the stack trace - will be reported correctly to the user. */ - /* XXX We should probably be updating the current frame - somewhere in ceval.c. */ + + /* Link frame into the stack to enable complete backtraces. */ tstate->frame = gen->gi_frame; tstate->shadow_frame = &gen->gi_shadow_frame; /* Close the generator that we are currently iterating with @@ -678,9 +675,17 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, Py_DECREF(yf); goto throw_here; } + tstate->frame = gen->gi_frame; + tstate->shadow_frame = &gen->gi_shadow_frame; CI_WITH_GEN_MARKED_AS_THROWING(gen, { ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL); }); + if (old_ptr_kind != PYSF_PYFRAME && _PyShadowFrame_GetPtrKind(sf) == PYSF_PYFRAME) { + /* Frame was materialized while throwing into yf */ + f = _PyShadowFrame_GetPyFrame(sf); + } + tstate->frame = f; + tstate->shadow_frame = sf; Py_DECREF(meth); } Py_DECREF(yf);