From: Mark Shannon Date: Thu, 8 Jul 2021 18:21:09 +0000 (+0100) Subject: bpo-44570: Fix line tracing for forwards jumps to duplicated tails (GH-27068) X-Git-Tag: v3.11.0a1~707 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=da6414f0acf5ec9ea3b07e4b3907bc49c2a61e2f;p=thirdparty%2FPython%2Fcpython.git bpo-44570: Fix line tracing for forwards jumps to duplicated tails (GH-27068) --- diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 5f2b908d87ac..c42c69d0c807 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -1041,6 +1041,41 @@ class TraceTestCase(unittest.TestCase): (-8, 'return'), (1, 'return')]) + def test_flow_converges_on_same_line(self): + + def foo(x): + if x: + try: + 1/(x - 1) + except ZeroDivisionError: + pass + return x + + def func(): + for i in range(2): + foo(i) + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (-8, 'call'), + (-7, 'line'), + (-2, 'line'), + (-2, 'return'), + (1, 'line'), + (2, 'line'), + (-8, 'call'), + (-7, 'line'), + (-6, 'line'), + (-5, 'line'), + (-5, 'exception'), + (-4, 'line'), + (-3, 'line'), + (-2, 'line'), + (-2, 'return'), + (1, 'line'), + (1, 'return')]) class SkipLineEventsTraceTestCase(TraceTestCase): """Repeat the trace tests, but with per-line events skipped""" diff --git a/Python/ceval.c b/Python/ceval.c index 611a39de75d1..22184058af2d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5476,10 +5476,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, int lastline = _PyCode_CheckLineNumber(instr_prev*2, &tstate->trace_info.bounds); int line = _PyCode_CheckLineNumber(frame->f_lasti*2, &tstate->trace_info.bounds); if (line != -1 && frame->f_trace_lines) { - /* Trace backward edges or first instruction of a new line */ - if (frame->f_lasti < instr_prev || - (line != lastline && frame->f_lasti*2 == tstate->trace_info.bounds.ar_start)) - { + /* Trace backward edges or if line number has changed */ + if (frame->f_lasti < instr_prev || line != lastline) { result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None); } }