]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-96864: Check for error between line and opcode events (GH-96880)
authorBrandt Bucher <brandtbucher@microsoft.com>
Mon, 19 Sep 2022 21:02:24 +0000 (14:02 -0700)
committerGitHub <noreply@github.com>
Mon, 19 Sep 2022 21:02:24 +0000 (14:02 -0700)
Lib/test/test_sys_settrace.py
Misc/NEWS.d/next/Core and Builtins/2022-09-16-12-36-13.gh-issue-96864.PLU3i8.rst [new file with mode: 0644]
Python/ceval.c

index 9f1aa81dbcd249ce60769c3179b417d713dc1173..aa61f8b185883b68b22ac6e0780afed9ff9ca58a 100644 (file)
@@ -1721,6 +1721,20 @@ class RaisingTraceFuncTestCase(unittest.TestCase):
         finally:
             sys.settrace(existing)
 
+    def test_line_event_raises_before_opcode_event(self):
+        exception = ValueError("BOOM!")
+        def trace(frame, event, arg):
+            if event == "line":
+                raise exception
+            frame.f_trace_opcodes = True
+            return trace
+        def f():
+            pass
+        with self.assertRaises(ValueError) as caught:
+            sys.settrace(trace)
+            f()
+        self.assertIs(caught.exception, exception)
+
 
 # 'Jump' tests: assigning to frame.f_lineno within a trace function
 # moves the execution position - it's how debuggers implement a Jump
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-16-12-36-13.gh-issue-96864.PLU3i8.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-16-12-36-13.gh-issue-96864.PLU3i8.rst
new file mode 100644 (file)
index 0000000..c0d41ae
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a possible assertion failure, fatal error, or :exc:`SystemError` if a
+line tracing event raises an exception while opcode tracing is enabled.
index 8891d6cfa07a153e1342e5d3e25c131b432a8e1c..a07fb4964b48f05dbdf8dc4bba644ec0a9700a51 100644 (file)
@@ -6293,7 +6293,7 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
         }
     }
     /* Always emit an opcode event if we're tracing all opcodes. */
-    if (f->f_trace_opcodes) {
+    if (f->f_trace_opcodes && result == 0) {
         result = call_trace(func, obj, tstate, frame, PyTrace_OPCODE, Py_None);
     }
     return result;