From 16632de6b21a98ef892458f72fcf4f1ba5137309 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 4 Aug 2023 21:22:38 +0100 Subject: [PATCH 1/5] Make signature of PY_THROW callabck match other exception monitoring callbacks. --- Include/internal/pycore_instruments.h | 4 ---- Python/ceval.c | 2 +- Python/instrumentation.c | 10 ---------- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index ccccd54a2f70a2..56de9f87171484 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -90,10 +90,6 @@ extern int _Py_call_instrumentation_2args(PyThreadState *tstate, int event, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); -extern void -_Py_call_instrumentation_exc0(PyThreadState *tstate, int event, - _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); - extern void _Py_call_instrumentation_exc2(PyThreadState *tstate, int event, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); diff --git a/Python/ceval.c b/Python/ceval.c index 30f722e45e476b..2cbc5f72512120 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2017,7 +2017,7 @@ monitor_throw(PyThreadState *tstate, if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_PY_THROW)) { return; } - _Py_call_instrumentation_exc0(tstate, PY_MONITORING_EVENT_PY_THROW, frame, instr); + do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_THROW); } void diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 123c20dfe1a99b..65ea7902a80a60 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1081,16 +1081,6 @@ call_instrumentation_vector_protected( assert(_PyErr_Occurred(tstate)); } -void -_Py_call_instrumentation_exc0( - PyThreadState *tstate, int event, - _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) -{ - assert(_PyErr_Occurred(tstate)); - PyObject *args[3] = { NULL, NULL, NULL }; - call_instrumentation_vector_protected(tstate, event, frame, instr, 2, args); -} - void _Py_call_instrumentation_exc2( PyThreadState *tstate, int event, From dac7358071db8d845fba3bf3bfe981216b5417ea Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 4 Aug 2023 21:25:41 +0100 Subject: [PATCH 2/5] Add news --- .../2023-08-04-21-25-26.gh-issue-107724.EbBXMr.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-08-04-21-25-26.gh-issue-107724.EbBXMr.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-04-21-25-26.gh-issue-107724.EbBXMr.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-04-21-25-26.gh-issue-107724.EbBXMr.rst new file mode 100644 index 00000000000000..6e853cf72a3348 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-08-04-21-25-26.gh-issue-107724.EbBXMr.rst @@ -0,0 +1,3 @@ +In pre-release versions of 3.12, up to rc1, the sys.monitoring callback +function for the ``PY_THROW`` event was missing the third, exception +argument. That is now fixed. From 119e206fb9405a98020332e7ae610117539e4229 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 4 Aug 2023 21:41:08 +0100 Subject: [PATCH 3/5] Add test for PY_THROW --- Lib/test/test_monitoring.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index b36382c8d0982d..e67439089e1c4d 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -709,6 +709,7 @@ def check_events(self, func, expected, tool=TEST_TOOL, recorders=(ExceptionRecor def check_balanced(self, func, recorders): events = self.get_events(func, TEST_TOOL, recorders) + print("----\n", events, "\n------") self.assertEqual(len(events)%2, 0) for r, h in zip(events[::2],events[1::2]): r0 = r[0] @@ -743,6 +744,13 @@ class ExceptionHandledRecorder(ExceptionRecorder): def __call__(self, code, offset, exc): self.events.append(("handled", type(exc))) +class ThrowRecorder(ExceptionRecorder): + + event_type = E.PY_THROW + + def __call__(self, code, offset, exc): + self.events.append(("throw", type(exc))) + class ExceptionMonitoringTest(CheckEvents): @@ -888,6 +896,31 @@ async def async_loop(): func, recorders = self.exception_recorders) + def test_throw(self): + + def gen(): + yield 1 + yield 2 + + def func(): + try: + g = gen() + next(g) + g.throw(IndexError) + except IndexError: + pass + + self.check_balanced( + func, + recorders = self.exception_recorders) + + events = self.get_events( + func, + TEST_TOOL, + self.exception_recorders + (ThrowRecorder,) + ) + self.assertEqual(events[0], ("throw", IndexError)) + class LineRecorder: event_type = E.LINE From 8f1380b61542605be4583d681671d14f4b94797b Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 4 Aug 2023 23:31:29 +0100 Subject: [PATCH 4/5] Fix legacy tracing shim --- Python/legacy_tracing.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c index 48db51731cfdb0..7774d10b10172b 100644 --- a/Python/legacy_tracing.c +++ b/Python/legacy_tracing.c @@ -163,7 +163,7 @@ sys_trace_func2( } static PyObject * -sys_trace_unwind( +sys_trace_func3( _PyLegacyEventHandler *self, PyObject *const *args, size_t nargsf, PyObject *kwnames ) { @@ -445,7 +445,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) return -1; } if (set_callbacks(PY_MONITORING_SYS_TRACE_ID, - (vectorcallfunc)sys_trace_func2, PyTrace_CALL, + (vectorcallfunc)sys_trace_func3, PyTrace_CALL, PY_MONITORING_EVENT_PY_THROW, -1)) { return -1; } @@ -470,7 +470,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) return -1; } if (set_callbacks(PY_MONITORING_SYS_TRACE_ID, - (vectorcallfunc)sys_trace_unwind, PyTrace_RETURN, + (vectorcallfunc)sys_trace_func3, PyTrace_RETURN, PY_MONITORING_EVENT_PY_UNWIND, -1)) { return -1; } From 8fe9166b08e052cd2c40d43cbfb5f3fe441654c5 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 8 Aug 2023 08:45:00 +0100 Subject: [PATCH 5/5] Remove debugging code Co-authored-by: Carl Meyer --- Lib/test/test_monitoring.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index e67439089e1c4d..845185be737eb2 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -709,7 +709,6 @@ def check_events(self, func, expected, tool=TEST_TOOL, recorders=(ExceptionRecor def check_balanced(self, func, recorders): events = self.get_events(func, TEST_TOOL, recorders) - print("----\n", events, "\n------") self.assertEqual(len(events)%2, 0) for r, h in zip(events[::2],events[1::2]): r0 = r[0]