Issue 1454: Generators break trace functionality (original) (raw)
I rely heavily on a code coverage analysis engine I developed, and a bug in Python's trace functionality has been bothering me for years. Today I snapped, and finally tracked it down to a minimal test case. To see the problem, play with the following code:
import sys
def run(): yield 1
def trace(frame, event, arg): try: for i in []: pass except Exception, e: pass
sys.settrace(trace) x = run() del x
Remove the try clause, and re-run with a debug build of the interpreter for a different symptom. Add a print statement at the end to verify that the problem occurs when the generator object is deleted.
The problem occurs due to an interaction between generators and the trace functionality. When a generator is deleted, the gen_del function calls gen_close, which then sets a GeneratorExit exception. Eventually, PyEval_EvalFrameEx is called, with the throwflag set. At this point the trace function is called, the GeneratorExit exception which is set causes problems with the FOR_ITER opcode, which then fails.
The attached patch against trunk fixes this by storing exceptions before the call trace function is called, and restoring the exception afterwards. All regression tests pass for me with this patch applied.