-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
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