Skip to content

Commit 04ec7a1

Browse files
authored
bpo-39114: Fix tracing of except handlers with name binding (GH-17769)
When producing the bytecode of exception handlers with name binding (like `except Exception as e`) we need to produce a try-finally block to make sure that the name is deleted after the handler is executed to prevent cycles in the stack frame objects. The bytecode associated with this try-finally block does not have source lines associated and it was causing problems when the tracing functionality was running over it.
1 parent 149175c commit 04ec7a1

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

Lib/test/test_sys_settrace.py

+45
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,51 @@ def func():
481481
[(0, 'call'),
482482
(1, 'line')])
483483

484+
def test_18_except_with_name(self):
485+
def func():
486+
try:
487+
try:
488+
raise Exception
489+
except Exception as e:
490+
raise
491+
x = "Something"
492+
y = "Something"
493+
except Exception:
494+
pass
495+
496+
self.run_and_compare(func,
497+
[(0, 'call'),
498+
(1, 'line'),
499+
(2, 'line'),
500+
(3, 'line'),
501+
(3, 'exception'),
502+
(4, 'line'),
503+
(5, 'line'),
504+
(8, 'line'),
505+
(9, 'line'),
506+
(9, 'return')])
507+
508+
def test_19_except_with_finally(self):
509+
def func():
510+
try:
511+
try:
512+
raise Exception
513+
finally:
514+
y = "Something"
515+
except Exception:
516+
b = 23
517+
518+
self.run_and_compare(func,
519+
[(0, 'call'),
520+
(1, 'line'),
521+
(2, 'line'),
522+
(3, 'line'),
523+
(3, 'exception'),
524+
(5, 'line'),
525+
(6, 'line'),
526+
(7, 'line'),
527+
(7, 'return')])
528+
484529

485530
class SkipLineEventsTraceTestCase(TraceTestCase):
486531
"""Repeat the trace tests, but with per-line events skipped"""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix incorrent line execution reporting in trace functions when tracing
2+
exception handlers with name binding. Patch by Pablo Galindo.

Python/ceval.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -3610,7 +3610,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
36103610
PUSH(val);
36113611
PUSH(exc);
36123612
JUMPTO(handler);
3613-
if (_Py_TracingPossible(ceval)) {
3613+
if (_Py_TracingPossible(ceval) &&
3614+
((f->f_lasti < instr_lb || f->f_lasti >= instr_ub) ||
3615+
!(f->f_lasti == instr_lb || f->f_lasti < instr_prev))) {
36143616
/* Make sure that we trace line after exception */
36153617
instr_prev = INT_MAX;
36163618
}

0 commit comments

Comments
 (0)