bpo-29590: fix stack trace for gen.throw() with yield from (GH-19896)
* Add failing test.
* bpo-29590: fix stack trace for gen.throw() with yield from (GH-NNNN)
When gen.throw() is called on a generator after a "yield from", the
intermediate stack trace entries are lost. This commit fixes that.
(cherry picked from commit 8b33961e4bc4020d8b2d5b949ad9d5c669300e89)
Co-authored-by: Chris Jerdonek <chris.jerdonek@gmail.com>
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 09efbab..72c93f6 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -414,11 +414,21 @@
}
if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
/* `yf` is a generator or a coroutine. */
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyFrameObject *f = tstate->frame;
+
gen->gi_running = 1;
+ /* 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. */
+ tstate->frame = gen->gi_frame;
/* Close the generator that we are currently iterating with
'yield from' or awaiting on with 'await'. */
ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
typ, val, tb);
+ tstate->frame = f;
gen->gi_running = 0;
} else {
/* `yf` is an iterator or a coroutine-like object. */