From fd1bc9412e48dc7bc0a6f4aef27f3af5c6cc96ab Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Sep 2023 12:24:35 +0100 Subject: [PATCH 1/3] assert lineno and lasti agree. Remove prev_instr setting in _Py_call_instrumentation_jump --- Lib/test/test_sys_settrace.py | 9 +++++++++ Python/instrumentation.c | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 53ec4eaea64b10..3e3eb632e1040d 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -303,6 +303,13 @@ def generator_example(): [(5, 'line'), (5, 'return')]) +def lineno_matches_lasti(frame): + last_line = None + for start, end, line in frame.f_code.co_lines(): + if start <= frame.f_lasti < end: + last_line = line + return last_line == frame.f_lineno + class Tracer: def __init__(self, trace_line_events=None, trace_opcode_events=None): self.trace_line_events = trace_line_events @@ -316,6 +323,8 @@ def _reconfigure_frame(self, frame): frame.f_trace_opcodes = self.trace_opcode_events def trace(self, frame, event, arg): + if event == 'line': + assert lineno_matches_lasti(frame) self._reconfigure_frame(frame) self.events.append((frame.f_lineno, event)) return self.trace diff --git a/Python/instrumentation.c b/Python/instrumentation.c index acc3278d50a60a..80ebe2fbd8d59b 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1058,7 +1058,7 @@ _Py_call_instrumentation_jump( event == PY_MONITORING_EVENT_BRANCH); assert(frame->prev_instr == instr); /* Event should occur after the jump */ - frame->prev_instr = target; + // frame->prev_instr = target; PyCodeObject *code = _PyFrame_GetCode(frame); int to = (int)(target - _PyCode_CODE(code)); PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT)); @@ -1071,12 +1071,12 @@ _Py_call_instrumentation_jump( if (err) { return NULL; } - if (frame->prev_instr != target) { + if (frame->prev_instr != instr) { /* The callback has caused a jump (by setting the line number) */ return frame->prev_instr; } /* Reset prev_instr for INSTRUMENTED_LINE */ - frame->prev_instr = instr; + // frame->prev_instr = instr; return target; } From 9d47c9775198a401d5116483bb46acf5e225e186 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Sep 2023 13:00:49 +0100 Subject: [PATCH 2/3] assert in jump tracer and all event in the line tracer --- Lib/test/test_sys_settrace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 3e3eb632e1040d..a41b845e4de6b6 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -323,8 +323,7 @@ def _reconfigure_frame(self, frame): frame.f_trace_opcodes = self.trace_opcode_events def trace(self, frame, event, arg): - if event == 'line': - assert lineno_matches_lasti(frame) + assert lineno_matches_lasti(frame) self._reconfigure_frame(frame) self.events.append((frame.f_lineno, event)) return self.trace @@ -1886,6 +1885,7 @@ def __init__(self, function, jumpFrom, jumpTo, event='line', def trace(self, frame, event, arg): if self.done: return + assert lineno_matches_lasti(frame) # frame.f_code.co_firstlineno is the first line of the decorator when # 'function' is decorated and the decorator may be written using # multiple physical lines when it is too long. Use the first line From a50201b83f610e5ac4fc46f003b894637ffcc1a3 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Sep 2023 17:14:03 +0100 Subject: [PATCH 3/3] remove commented out code and turn assignment to assertion --- Python/instrumentation.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 80ebe2fbd8d59b..74c3adf0c1f475 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1057,8 +1057,6 @@ _Py_call_instrumentation_jump( assert(event == PY_MONITORING_EVENT_JUMP || event == PY_MONITORING_EVENT_BRANCH); assert(frame->prev_instr == instr); - /* Event should occur after the jump */ - // frame->prev_instr = target; PyCodeObject *code = _PyFrame_GetCode(frame); int to = (int)(target - _PyCode_CODE(code)); PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT)); @@ -1075,8 +1073,6 @@ _Py_call_instrumentation_jump( /* The callback has caused a jump (by setting the line number) */ return frame->prev_instr; } - /* Reset prev_instr for INSTRUMENTED_LINE */ - // frame->prev_instr = instr; return target; } @@ -1125,7 +1121,7 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index) int _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev) { - frame->prev_instr = instr; + assert(frame->prev_instr == instr); PyCodeObject *code = _PyFrame_GetCode(frame); assert(is_version_up_to_date(code, tstate->interp)); assert(instrumentation_cross_checks(tstate->interp, code));