aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/legacy_tracing.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/legacy_tracing.c')
-rw-r--r--Python/legacy_tracing.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c
index ddc727113af..ccbb3eb3f7c 100644
--- a/Python/legacy_tracing.c
+++ b/Python/legacy_tracing.c
@@ -117,6 +117,35 @@ sys_profile_call_or_return(
Py_RETURN_NONE;
}
+int
+_PyEval_SetOpcodeTrace(
+ PyFrameObject *frame,
+ bool enable
+) {
+ assert(frame != NULL);
+ assert(PyCode_Check(frame->f_frame->f_executable));
+
+ PyCodeObject *code = (PyCodeObject *)frame->f_frame->f_executable;
+ _PyMonitoringEventSet events = 0;
+
+ if (_PyMonitoring_GetLocalEvents(code, PY_MONITORING_SYS_TRACE_ID, &events) < 0) {
+ return -1;
+ }
+
+ if (enable) {
+ if (events & (1 << PY_MONITORING_EVENT_INSTRUCTION)) {
+ return 0;
+ }
+ events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);
+ } else {
+ if (!(events & (1 << PY_MONITORING_EVENT_INSTRUCTION))) {
+ return 0;
+ }
+ events &= (~(1 << PY_MONITORING_EVENT_INSTRUCTION));
+ }
+ return _PyMonitoring_SetLocalEvents(code, PY_MONITORING_SYS_TRACE_ID, events);
+}
+
static PyObject *
call_trace_func(_PyLegacyEventHandler *self, PyObject *arg)
{
@@ -130,6 +159,12 @@ call_trace_func(_PyLegacyEventHandler *self, PyObject *arg)
"Missing frame when calling trace function.");
return NULL;
}
+ if (frame->f_trace_opcodes) {
+ if (_PyEval_SetOpcodeTrace(frame, true) != 0) {
+ return NULL;
+ }
+ }
+
Py_INCREF(frame);
int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, arg);
Py_DECREF(frame);
@@ -230,11 +265,14 @@ sys_trace_instruction_func(
"Missing frame when calling trace function.");
return NULL;
}
- if (!frame->f_trace_opcodes) {
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (!tstate->c_tracefunc || !frame->f_trace_opcodes) {
+ if (_PyEval_SetOpcodeTrace(frame, false) != 0) {
+ return NULL;
+ }
Py_RETURN_NONE;
}
Py_INCREF(frame);
- PyThreadState *tstate = _PyThreadState_GET();
int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);
frame->f_lineno = 0;
Py_DECREF(frame);
@@ -531,9 +569,15 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
(1 << PY_MONITORING_EVENT_PY_UNWIND) | (1 << PY_MONITORING_EVENT_PY_THROW) |
(1 << PY_MONITORING_EVENT_STOP_ITERATION) |
(1 << PY_MONITORING_EVENT_EXCEPTION_HANDLED);
- if (tstate->interp->f_opcode_trace_set) {
- events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);
+
+ PyFrameObject* frame = PyEval_GetFrame();
+ if (frame->f_trace_opcodes) {
+ int ret = _PyEval_SetOpcodeTrace(frame, true);
+ if (ret != 0) {
+ return ret;
+ }
}
}
+
return _PyMonitoring_SetEvents(PY_MONITORING_SYS_TRACE_ID, events);
}