diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py index bb8adc8b555cb4..32e03d7cd25dbe 100644 --- a/Lib/test/test_sys_setprofile.py +++ b/Lib/test/test_sys_setprofile.py @@ -30,9 +30,9 @@ def callback(self, frame, event, arg): 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 @@ def add_event(self, event, frame=None): 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 @@ def trace_pass(self, frame): 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 @@ def g(p): 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 index 00000000000000..4422273d51757c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-15-20-45-35.gh-issue-110892.oA6eVY.rst @@ -0,0 +1 @@ +Return ``NULL`` for ``PyTrace_RETURN`` events caused by an exception diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c index 97d39a14ae43d0..ddc727113af334 100644 --- a/Python/legacy_tracing.c +++ b/Python/legacy_tracing.c @@ -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; }