]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110892: Return NULL for `PyTrace_RETURN` events caused by an exception (GH-110909)
authorTian Gao <gaogaotiantian@hotmail.com>
Thu, 2 Nov 2023 16:38:08 +0000 (09:38 -0700)
committerGitHub <noreply@github.com>
Thu, 2 Nov 2023 16:38:08 +0000 (16:38 +0000)
Lib/test/test_sys_setprofile.py
Misc/NEWS.d/next/Core and Builtins/2023-10-15-20-45-35.gh-issue-110892.oA6eVY.rst [new file with mode: 0644]
Python/legacy_tracing.c

index bb8adc8b555cb4cd670829de3824f5c08fabd8e0..32e03d7cd25dbef6c02ee1df2941e48446845abf 100644 (file)
@@ -30,9 +30,9 @@ class HookWatcher:
         if (event == "call"
             or event == "return"
             or event == "exception"):
-            self.add_event(event, frame)
+            self.add_event(event, frame, arg)
 
-    def add_event(self, event, frame=None):
+    def add_event(self, event, frame=None, arg=None):
         """Add an event to the log."""
         if frame is None:
             frame = sys._getframe(1)
@@ -43,7 +43,7 @@ class HookWatcher:
             frameno = len(self.frames)
             self.frames.append(frame)
 
-        self.events.append((frameno, event, ident(frame)))
+        self.events.append((frameno, event, ident(frame), arg))
 
     def get_events(self):
         """Remove calls to add_event()."""
@@ -89,11 +89,16 @@ class ProfileSimulator(HookWatcher):
 
 
 class TestCaseBase(unittest.TestCase):
-    def check_events(self, callable, expected):
+    def check_events(self, callable, expected, check_args=False):
         events = capture_events(callable, self.new_watcher())
-        if events != expected:
-            self.fail("Expected events:\n%s\nReceived events:\n%s"
-                      % (pprint.pformat(expected), pprint.pformat(events)))
+        if check_args:
+            if events != expected:
+                self.fail("Expected events:\n%s\nReceived events:\n%s"
+                          % (pprint.pformat(expected), pprint.pformat(events)))
+        else:
+            if [(frameno, event, ident) for frameno, event, ident, arg in events] != expected:
+                self.fail("Expected events:\n%s\nReceived events:\n%s"
+                          % (pprint.pformat(expected), pprint.pformat(events)))
 
 
 class ProfileHookTestCase(TestCaseBase):
@@ -264,11 +269,11 @@ class ProfileHookTestCase(TestCaseBase):
 
         f_ident = ident(f)
         g_ident = ident(g)
-        self.check_events(g, [(1, 'call', g_ident),
-                              (2, 'call', f_ident),
-                              (2, 'return', f_ident),
-                              (1, 'return', g_ident),
-                              ])
+        self.check_events(g, [(1, 'call', g_ident, None),
+                              (2, 'call', f_ident, None),
+                              (2, 'return', f_ident, 0),
+                              (1, 'return', g_ident, None),
+                              ], check_args=True)
 
     def test_stop_iteration(self):
         def f():
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-15-20-45-35.gh-issue-110892.oA6eVY.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-15-20-45-35.gh-issue-110892.oA6eVY.rst
new file mode 100644 (file)
index 0000000..4422273
--- /dev/null
@@ -0,0 +1 @@
+Return ``NULL`` for ``PyTrace_RETURN`` events caused by an exception
index 97d39a14ae43d09de589cdd229fd162c119f3d9c..ddc727113af3341a3928306077acf6fa089fbc7c 100644 (file)
@@ -46,7 +46,7 @@ call_profile_func(_PyLegacyEventHandler *self, PyObject *arg)
 }
 
 static PyObject *
-sys_profile_func2(
+sys_profile_start(
     _PyLegacyEventHandler *self, PyObject *const *args,
     size_t nargsf, PyObject *kwnames
 ) {
@@ -56,7 +56,17 @@ sys_profile_func2(
 }
 
 static PyObject *
-sys_profile_func3(
+sys_profile_throw(
+    _PyLegacyEventHandler *self, PyObject *const *args,
+    size_t nargsf, PyObject *kwnames
+) {
+    assert(kwnames == NULL);
+    assert(PyVectorcall_NARGS(nargsf) == 3);
+    return call_profile_func(self, Py_None);
+}
+
+static PyObject *
+sys_profile_return(
     _PyLegacyEventHandler *self, PyObject *const *args,
     size_t nargsf, PyObject *kwnames
 ) {
@@ -72,7 +82,7 @@ sys_profile_unwind(
 ) {
     assert(kwnames == NULL);
     assert(PyVectorcall_NARGS(nargsf) == 3);
-    return call_profile_func(self, Py_None);
+    return call_profile_func(self, NULL);
 }
 
 static PyObject *
@@ -154,7 +164,7 @@ sys_trace_exception_func(
 }
 
 static PyObject *
-sys_trace_func2(
+sys_trace_start(
     _PyLegacyEventHandler *self, PyObject *const *args,
     size_t nargsf, PyObject *kwnames
 ) {
@@ -164,7 +174,7 @@ sys_trace_func2(
 }
 
 static PyObject *
-sys_trace_func3(
+sys_trace_throw(
     _PyLegacyEventHandler *self, PyObject *const *args,
     size_t nargsf, PyObject *kwnames
 ) {
@@ -173,6 +183,16 @@ sys_trace_func3(
     return call_trace_func(self, Py_None);
 }
 
+static PyObject *
+sys_trace_unwind(
+    _PyLegacyEventHandler *self, PyObject *const *args,
+    size_t nargsf, PyObject *kwnames
+) {
+    assert(kwnames == NULL);
+    assert(PyVectorcall_NARGS(nargsf) == 3);
+    return call_trace_func(self, NULL);
+}
+
 static PyObject *
 sys_trace_return(
     _PyLegacyEventHandler *self, PyObject *const *args,
@@ -373,17 +393,17 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
     if (!tstate->interp->sys_profile_initialized) {
         tstate->interp->sys_profile_initialized = true;
         if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
-            (vectorcallfunc)sys_profile_func2, PyTrace_CALL,
+            (vectorcallfunc)sys_profile_start, PyTrace_CALL,
                         PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
             return -1;
         }
         if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
-            (vectorcallfunc)sys_profile_func3, PyTrace_CALL,
+            (vectorcallfunc)sys_profile_throw, PyTrace_CALL,
                         PY_MONITORING_EVENT_PY_THROW, -1)) {
             return -1;
         }
         if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
-            (vectorcallfunc)sys_profile_func3, PyTrace_RETURN,
+            (vectorcallfunc)sys_profile_return, PyTrace_RETURN,
                         PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) {
             return -1;
         }
@@ -447,12 +467,12 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
     if (!tstate->interp->sys_trace_initialized) {
         tstate->interp->sys_trace_initialized = true;
         if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
-            (vectorcallfunc)sys_trace_func2, PyTrace_CALL,
+            (vectorcallfunc)sys_trace_start, PyTrace_CALL,
                         PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
             return -1;
         }
         if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
-            (vectorcallfunc)sys_trace_func3, PyTrace_CALL,
+            (vectorcallfunc)sys_trace_throw, PyTrace_CALL,
                         PY_MONITORING_EVENT_PY_THROW, -1)) {
             return -1;
         }
@@ -477,7 +497,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
             return -1;
         }
         if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
-            (vectorcallfunc)sys_trace_func3, PyTrace_RETURN,
+            (vectorcallfunc)sys_trace_unwind, PyTrace_RETURN,
                         PY_MONITORING_EVENT_PY_UNWIND, -1)) {
             return -1;
         }