mirror of
https://github.com/python/cpython.git
synced 2025-10-21 22:22:48 +00:00
gh-110892: Return NULL for PyTrace_RETURN
events caused by an exception (GH-110909)
This commit is contained in:
parent
0887b9ce8b
commit
f4b5588bde
3 changed files with 49 additions and 23 deletions
|
@ -30,9 +30,9 @@ class HookWatcher:
|
||||||
if (event == "call"
|
if (event == "call"
|
||||||
or event == "return"
|
or event == "return"
|
||||||
or event == "exception"):
|
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."""
|
"""Add an event to the log."""
|
||||||
if frame is None:
|
if frame is None:
|
||||||
frame = sys._getframe(1)
|
frame = sys._getframe(1)
|
||||||
|
@ -43,7 +43,7 @@ class HookWatcher:
|
||||||
frameno = len(self.frames)
|
frameno = len(self.frames)
|
||||||
self.frames.append(frame)
|
self.frames.append(frame)
|
||||||
|
|
||||||
self.events.append((frameno, event, ident(frame)))
|
self.events.append((frameno, event, ident(frame), arg))
|
||||||
|
|
||||||
def get_events(self):
|
def get_events(self):
|
||||||
"""Remove calls to add_event()."""
|
"""Remove calls to add_event()."""
|
||||||
|
@ -89,11 +89,16 @@ class ProfileSimulator(HookWatcher):
|
||||||
|
|
||||||
|
|
||||||
class TestCaseBase(unittest.TestCase):
|
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())
|
events = capture_events(callable, self.new_watcher())
|
||||||
if events != expected:
|
if check_args:
|
||||||
self.fail("Expected events:\n%s\nReceived events:\n%s"
|
if events != expected:
|
||||||
% (pprint.pformat(expected), pprint.pformat(events)))
|
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):
|
class ProfileHookTestCase(TestCaseBase):
|
||||||
|
@ -264,11 +269,11 @@ class ProfileHookTestCase(TestCaseBase):
|
||||||
|
|
||||||
f_ident = ident(f)
|
f_ident = ident(f)
|
||||||
g_ident = ident(g)
|
g_ident = ident(g)
|
||||||
self.check_events(g, [(1, 'call', g_ident),
|
self.check_events(g, [(1, 'call', g_ident, None),
|
||||||
(2, 'call', f_ident),
|
(2, 'call', f_ident, None),
|
||||||
(2, 'return', f_ident),
|
(2, 'return', f_ident, 0),
|
||||||
(1, 'return', g_ident),
|
(1, 'return', g_ident, None),
|
||||||
])
|
], check_args=True)
|
||||||
|
|
||||||
def test_stop_iteration(self):
|
def test_stop_iteration(self):
|
||||||
def f():
|
def f():
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Return ``NULL`` for ``PyTrace_RETURN`` events caused by an exception
|
|
@ -46,7 +46,7 @@ call_profile_func(_PyLegacyEventHandler *self, PyObject *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sys_profile_func2(
|
sys_profile_start(
|
||||||
_PyLegacyEventHandler *self, PyObject *const *args,
|
_PyLegacyEventHandler *self, PyObject *const *args,
|
||||||
size_t nargsf, PyObject *kwnames
|
size_t nargsf, PyObject *kwnames
|
||||||
) {
|
) {
|
||||||
|
@ -56,7 +56,17 @@ sys_profile_func2(
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
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,
|
_PyLegacyEventHandler *self, PyObject *const *args,
|
||||||
size_t nargsf, PyObject *kwnames
|
size_t nargsf, PyObject *kwnames
|
||||||
) {
|
) {
|
||||||
|
@ -72,7 +82,7 @@ sys_profile_unwind(
|
||||||
) {
|
) {
|
||||||
assert(kwnames == NULL);
|
assert(kwnames == NULL);
|
||||||
assert(PyVectorcall_NARGS(nargsf) == 3);
|
assert(PyVectorcall_NARGS(nargsf) == 3);
|
||||||
return call_profile_func(self, Py_None);
|
return call_profile_func(self, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -154,7 +164,7 @@ sys_trace_exception_func(
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sys_trace_func2(
|
sys_trace_start(
|
||||||
_PyLegacyEventHandler *self, PyObject *const *args,
|
_PyLegacyEventHandler *self, PyObject *const *args,
|
||||||
size_t nargsf, PyObject *kwnames
|
size_t nargsf, PyObject *kwnames
|
||||||
) {
|
) {
|
||||||
|
@ -164,7 +174,7 @@ sys_trace_func2(
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sys_trace_func3(
|
sys_trace_throw(
|
||||||
_PyLegacyEventHandler *self, PyObject *const *args,
|
_PyLegacyEventHandler *self, PyObject *const *args,
|
||||||
size_t nargsf, PyObject *kwnames
|
size_t nargsf, PyObject *kwnames
|
||||||
) {
|
) {
|
||||||
|
@ -173,6 +183,16 @@ sys_trace_func3(
|
||||||
return call_trace_func(self, Py_None);
|
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 *
|
static PyObject *
|
||||||
sys_trace_return(
|
sys_trace_return(
|
||||||
_PyLegacyEventHandler *self, PyObject *const *args,
|
_PyLegacyEventHandler *self, PyObject *const *args,
|
||||||
|
@ -373,17 +393,17 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
if (!tstate->interp->sys_profile_initialized) {
|
if (!tstate->interp->sys_profile_initialized) {
|
||||||
tstate->interp->sys_profile_initialized = true;
|
tstate->interp->sys_profile_initialized = true;
|
||||||
if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
|
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)) {
|
PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
|
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)) {
|
PY_MONITORING_EVENT_PY_THROW, -1)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
|
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)) {
|
PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -447,12 +467,12 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
if (!tstate->interp->sys_trace_initialized) {
|
if (!tstate->interp->sys_trace_initialized) {
|
||||||
tstate->interp->sys_trace_initialized = true;
|
tstate->interp->sys_trace_initialized = true;
|
||||||
if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
|
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)) {
|
PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
|
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)) {
|
PY_MONITORING_EVENT_PY_THROW, -1)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -477,7 +497,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
|
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)) {
|
PY_MONITORING_EVENT_PY_UNWIND, -1)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue