Bug report
Bug description:
Very similar to #151424, but this is not about impossible stack traces but implausible. :-)
Found while wrapping my head around #151424 and checking the source code for internals of last_profiled_frame.
Mechansim
The interpr has to advance tstate->last_profiled_frame for us. It does so in _PyEval_FrameClearAndPop:
|
if (tstate->last_profiled_frame != NULL && tstate->last_profiled_frame == frame) { |
But the helper not always used when a frame is removed from the chain.
Naively:
_YIELD_VALUE missed:
|
frame = tstate->current_frame = frame->previous; |
|
gen_frame->previous = NULL; |
RETURN_GENERATOR missed:
|
_PyThreadState_PopFrame(tstate, frame); |
_gen_throw missed:
|
tstate->current_frame = prev; |
|
tstate->current_frame = prev; |
frame-init fail missed:
|
clear_thread_frame(tstate, frame); |
Reproduction
def gen():
while True:
n = yield
sum(range(n))
g = gen()
next(g)
def drv_a(): g.send(5000)
def drv_b(): g.send(50000)
while True:
drv_a(); drv_b()
2026-06-13T11:41:14.582916000+0200 maurycy@gimel /Users/maurycy/work/cpython-main (main f4f1020?) % sudo ./python.exe -m profiling.sampling run --collapsed -o /tmp/stacks.txt -d 10 genrepro.py&& cat /tmp/stacks.txt
Captured 10,000 samples in 10.00 seconds
Sample rate: 999.99 samples/sec
Error rate: 0.01
Collapsed stack output written to /tmp/stacks.txt
tid:13788812;<frozen runpy>:_run_module_as_main:201;<frozen runpy>:_run_code:87;genrepro.py:<module>:13;genrepro.py:drv_b:10;genrepro.py:gen:4 9990
tid:13788812;<frozen runpy>:_run_module_as_main:201;<frozen runpy>:_run_code:87;genrepro.py:<module>:13;genrepro.py:drv_b:10;genrepro.py:gen:3 6
tid:13788812;<frozen runpy>:_run_module_as_main:201;<frozen runpy>:_run_code:87;genrepro.py:<module>:13 3
2026-06-13T11:41:27.285300000+0200 maurycy@gimel /Users/maurycy/work/cpython-main (main f4f1020?) %
Where is drv_a? TOTALLY_GONE.
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
Bug report
Bug description:
Very similar to #151424, but this is not about impossible stack traces but implausible. :-)
Found while wrapping my head around #151424 and checking the source code for internals of
last_profiled_frame.Mechansim
The interpr has to advance
tstate->last_profiled_framefor us. It does so in_PyEval_FrameClearAndPop:cpython/Python/ceval.c
Line 1981 in f4f1020
But the helper not always used when a frame is removed from the chain.
Naively:
_YIELD_VALUEmissed:cpython/Python/bytecodes.c
Lines 1863 to 1864 in f4f1020
RETURN_GENERATORmissed:cpython/Python/bytecodes.c
Line 5877 in f4f1020
_gen_throwmissed:cpython/Objects/genobject.c
Line 684 in f4f1020
cpython/Objects/genobject.c
Line 704 in f4f1020
frame-init fail missed:
cpython/Python/ceval.c
Line 2009 in f4f1020
Reproduction
Where is
drv_a?TOTALLY_GONE.CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
tstate->last_profiled_frameupdates #151437