diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2020-01-02 11:38:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-02 11:38:44 (GMT) |
commit | 04ec7a1f7a5b92187a73cd02670958444c6f2220 (patch) | |
tree | df7e34cd5c5ef3e80ce51ab6c6ad85dba37de8e0 | |
parent | 149175c6dfc8455023e4335575f3fe3d606729f9 (diff) | |
download | cpython-04ec7a1f7a5b92187a73cd02670958444c6f2220.zip cpython-04ec7a1f7a5b92187a73cd02670958444c6f2220.tar.gz cpython-04ec7a1f7a5b92187a73cd02670958444c6f2220.tar.bz2 |
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.
-rw-r--r-- | Lib/test/test_sys_settrace.py | 45 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2019-12-31-18-25-45.bpo-39114.WG9alt.rst | 2 | ||||
-rw-r--r-- | Python/ceval.c | 4 |
3 files changed, 50 insertions, 1 deletions
diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 0af015a..a0d1122 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -481,6 +481,51 @@ class TraceTestCase(unittest.TestCase): [(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""" diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-31-18-25-45.bpo-39114.WG9alt.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-31-18-25-45.bpo-39114.WG9alt.rst new file mode 100644 index 0000000..d742af9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-31-18-25-45.bpo-39114.WG9alt.rst @@ -0,0 +1,2 @@ +Fix incorrent line execution reporting in trace functions when tracing +exception handlers with name binding. Patch by Pablo Galindo. diff --git a/Python/ceval.c b/Python/ceval.c index 96ed329..bd9454b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3610,7 +3610,9 @@ exception_unwind: 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; } |