Skip to content

Commit f4b5588

Browse files
gh-110892: Return NULL for PyTrace_RETURN events caused by an exception (GH-110909)
1 parent 0887b9c commit f4b5588

File tree

3 files changed

+49
-23
lines changed

3 files changed

+49
-23
lines changed

Lib/test/test_sys_setprofile.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ def callback(self, frame, event, arg):
3030
if (event == "call"
3131
or event == "return"
3232
or event == "exception"):
33-
self.add_event(event, frame)
33+
self.add_event(event, frame, arg)
3434

35-
def add_event(self, event, frame=None):
35+
def add_event(self, event, frame=None, arg=None):
3636
"""Add an event to the log."""
3737
if frame is None:
3838
frame = sys._getframe(1)
@@ -43,7 +43,7 @@ def add_event(self, event, frame=None):
4343
frameno = len(self.frames)
4444
self.frames.append(frame)
4545

46-
self.events.append((frameno, event, ident(frame)))
46+
self.events.append((frameno, event, ident(frame), arg))
4747

4848
def get_events(self):
4949
"""Remove calls to add_event()."""
@@ -89,11 +89,16 @@ def trace_pass(self, frame):
8989

9090

9191
class TestCaseBase(unittest.TestCase):
92-
def check_events(self, callable, expected):
92+
def check_events(self, callable, expected, check_args=False):
9393
events = capture_events(callable, self.new_watcher())
94-
if events != expected:
95-
self.fail("Expected events:\n%s\nReceived events:\n%s"
96-
% (pprint.pformat(expected), pprint.pformat(events)))
94+
if check_args:
95+
if events != expected:
96+
self.fail("Expected events:\n%s\nReceived events:\n%s"
97+
% (pprint.pformat(expected), pprint.pformat(events)))
98+
else:
99+
if [(frameno, event, ident) for frameno, event, ident, arg in events] != expected:
100+
self.fail("Expected events:\n%s\nReceived events:\n%s"
101+
% (pprint.pformat(expected), pprint.pformat(events)))
97102

98103

99104
class ProfileHookTestCase(TestCaseBase):
@@ -264,11 +269,11 @@ def g(p):
264269

265270
f_ident = ident(f)
266271
g_ident = ident(g)
267-
self.check_events(g, [(1, 'call', g_ident),
268-
(2, 'call', f_ident),
269-
(2, 'return', f_ident),
270-
(1, 'return', g_ident),
271-
])
272+
self.check_events(g, [(1, 'call', g_ident, None),
273+
(2, 'call', f_ident, None),
274+
(2, 'return', f_ident, 0),
275+
(1, 'return', g_ident, None),
276+
], check_args=True)
272277

273278
def test_stop_iteration(self):
274279
def f():
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Return ``NULL`` for ``PyTrace_RETURN`` events caused by an exception

Python/legacy_tracing.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ call_profile_func(_PyLegacyEventHandler *self, PyObject *arg)
4646
}
4747

4848
static PyObject *
49-
sys_profile_func2(
49+
sys_profile_start(
5050
_PyLegacyEventHandler *self, PyObject *const *args,
5151
size_t nargsf, PyObject *kwnames
5252
) {
@@ -56,7 +56,17 @@ sys_profile_func2(
5656
}
5757

5858
static PyObject *
59-
sys_profile_func3(
59+
sys_profile_throw(
60+
_PyLegacyEventHandler *self, PyObject *const *args,
61+
size_t nargsf, PyObject *kwnames
62+
) {
63+
assert(kwnames == NULL);
64+
assert(PyVectorcall_NARGS(nargsf) == 3);
65+
return call_profile_func(self, Py_None);
66+
}
67+
68+
static PyObject *
69+
sys_profile_return(
6070
_PyLegacyEventHandler *self, PyObject *const *args,
6171
size_t nargsf, PyObject *kwnames
6272
) {
@@ -72,7 +82,7 @@ sys_profile_unwind(
7282
) {
7383
assert(kwnames == NULL);
7484
assert(PyVectorcall_NARGS(nargsf) == 3);
75-
return call_profile_func(self, Py_None);
85+
return call_profile_func(self, NULL);
7686
}
7787

7888
static PyObject *
@@ -154,7 +164,7 @@ sys_trace_exception_func(
154164
}
155165

156166
static PyObject *
157-
sys_trace_func2(
167+
sys_trace_start(
158168
_PyLegacyEventHandler *self, PyObject *const *args,
159169
size_t nargsf, PyObject *kwnames
160170
) {
@@ -164,7 +174,7 @@ sys_trace_func2(
164174
}
165175

166176
static PyObject *
167-
sys_trace_func3(
177+
sys_trace_throw(
168178
_PyLegacyEventHandler *self, PyObject *const *args,
169179
size_t nargsf, PyObject *kwnames
170180
) {
@@ -173,6 +183,16 @@ sys_trace_func3(
173183
return call_trace_func(self, Py_None);
174184
}
175185

186+
static PyObject *
187+
sys_trace_unwind(
188+
_PyLegacyEventHandler *self, PyObject *const *args,
189+
size_t nargsf, PyObject *kwnames
190+
) {
191+
assert(kwnames == NULL);
192+
assert(PyVectorcall_NARGS(nargsf) == 3);
193+
return call_trace_func(self, NULL);
194+
}
195+
176196
static PyObject *
177197
sys_trace_return(
178198
_PyLegacyEventHandler *self, PyObject *const *args,
@@ -373,17 +393,17 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
373393
if (!tstate->interp->sys_profile_initialized) {
374394
tstate->interp->sys_profile_initialized = true;
375395
if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
376-
(vectorcallfunc)sys_profile_func2, PyTrace_CALL,
396+
(vectorcallfunc)sys_profile_start, PyTrace_CALL,
377397
PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
378398
return -1;
379399
}
380400
if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
381-
(vectorcallfunc)sys_profile_func3, PyTrace_CALL,
401+
(vectorcallfunc)sys_profile_throw, PyTrace_CALL,
382402
PY_MONITORING_EVENT_PY_THROW, -1)) {
383403
return -1;
384404
}
385405
if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
386-
(vectorcallfunc)sys_profile_func3, PyTrace_RETURN,
406+
(vectorcallfunc)sys_profile_return, PyTrace_RETURN,
387407
PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) {
388408
return -1;
389409
}
@@ -447,12 +467,12 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
447467
if (!tstate->interp->sys_trace_initialized) {
448468
tstate->interp->sys_trace_initialized = true;
449469
if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
450-
(vectorcallfunc)sys_trace_func2, PyTrace_CALL,
470+
(vectorcallfunc)sys_trace_start, PyTrace_CALL,
451471
PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
452472
return -1;
453473
}
454474
if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
455-
(vectorcallfunc)sys_trace_func3, PyTrace_CALL,
475+
(vectorcallfunc)sys_trace_throw, PyTrace_CALL,
456476
PY_MONITORING_EVENT_PY_THROW, -1)) {
457477
return -1;
458478
}
@@ -477,7 +497,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
477497
return -1;
478498
}
479499
if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
480-
(vectorcallfunc)sys_trace_func3, PyTrace_RETURN,
500+
(vectorcallfunc)sys_trace_unwind, PyTrace_RETURN,
481501
PY_MONITORING_EVENT_PY_UNWIND, -1)) {
482502
return -1;
483503
}

0 commit comments

Comments
 (0)