Description
Bug report
Bug description:
import sys
def f(*args):
pass
def bar():
yield 42
sys.settrace(f)
g = bar()
next(g)
The code above will trigger an assertion added in #109846.
python: Python/instrumentation.c:1576: _Py_Instrument: Assertion `(interp->ceval.eval_breaker & ~_PY_EVAL_EVENTS_MASK) == 0 || instrumentation_cross_checks(interp, code)' failed.
Aborted
The reason is that during the interpreter finalization, the global event monitors are reset to 0. However, the garbage collection triggered a send to the generator bar
which then triggered _Py_Instrument
.
is_version_up_to_date
is true because the the code was instrumented when last time eval_breaker
changed. However, instrumentation_cross_checks
would fail, because interp->monitors
is reset to 0
.
Notice that in the code example above, if the trace function f
returns itself rather than None
, the assertion failure won't trigger because the generator would not be garbage collected - this might be an instrumentation bug that made the generator uncollectable (I've confirmed that _PyGen_Finalize
and gen_close()
never executed). However, I did not connect the dots so I don't know why that did not work.
I've made a simple patch in the PR, where I reset the interp->ceval.eval_breaker = 0
in interpreter_clear
. It's kind of reasonable but I'm not knowledgeable enough to be confident that this is the/a correct fix.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux