Skip to content

Commit

Permalink
bpo-39114: Fix tracing of except handlers with name binding (GH-17769)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pablogsal committed Jan 2, 2020
1 parent 149175c commit 04ec7a1
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
45 changes: 45 additions & 0 deletions Lib/test/test_sys_settrace.py
Expand Up @@ -481,6 +481,51 @@ def func():
[(0, 'call'),
(1, 'line')])

def test_18_except_with_name(self):
def func():
try:
try:
raise Exception
except Exception as e:
raise
x = "Something"
y = "Something"
except Exception:
pass

self.run_and_compare(func,
[(0, 'call'),
(1, 'line'),
(2, 'line'),
(3, 'line'),
(3, 'exception'),
(4, 'line'),
(5, 'line'),
(8, 'line'),
(9, 'line'),
(9, 'return')])

def test_19_except_with_finally(self):
def func():
try:
try:
raise Exception
finally:
y = "Something"
except Exception:
b = 23

self.run_and_compare(func,
[(0, 'call'),
(1, 'line'),
(2, 'line'),
(3, 'line'),
(3, 'exception'),
(5, 'line'),
(6, 'line'),
(7, 'line'),
(7, 'return')])


class SkipLineEventsTraceTestCase(TraceTestCase):
"""Repeat the trace tests, but with per-line events skipped"""
Expand Down
@@ -0,0 +1,2 @@
Fix incorrent line execution reporting in trace functions when tracing
exception handlers with name binding. Patch by Pablo Galindo.
4 changes: 3 additions & 1 deletion Python/ceval.c
Expand Up @@ -3610,7 +3610,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
PUSH(val);
PUSH(exc);
JUMPTO(handler);
if (_Py_TracingPossible(ceval)) {
if (_Py_TracingPossible(ceval) &&
((f->f_lasti < instr_lb || f->f_lasti >= instr_ub) ||
!(f->f_lasti == instr_lb || f->f_lasti < instr_prev))) {
/* Make sure that we trace line after exception */
instr_prev = INT_MAX;
}
Expand Down

0 comments on commit 04ec7a1

Please sign in to comment.