From b2d19c391fc48ff4b82834a1fb5b9e3bc20fa641 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 6 Mar 2024 14:10:30 +0000 Subject: [PATCH 01/79] gh-111997: C-API for signalling monitoring events --- Include/internal/pycore_instruments.h | 83 +++++++ Modules/Setup.stdlib.in | 2 +- Modules/_testinternalcapi.c | 3 + Modules/_testinternalcapi/monitoring.c | 304 +++++++++++++++++++++++++ Modules/_testinternalcapi/parts.h | 1 + Python/instrumentation.c | 273 ++++++++++++++++++++++ 6 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 Modules/_testinternalcapi/monitoring.c diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index eae8371ef7f9b8f..b9a7dc05e45da93 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -101,6 +101,89 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index); extern PyObject _PyInstrumentation_MISSING; extern PyObject _PyInstrumentation_DISABLE; +typedef struct _PyMonitoringState { + uint8_t active; + uint8_t opaque; +} PyMonitoringState; + + +/*** C API ***/ + +PyAPI_FUNC(void) +_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + +PyAPI_FUNC(int) +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + + +PyAPI_FUNC(int) +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); + +PyAPI_FUNC(int) +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + + +PyAPI_FUNC(int) +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + #ifdef __cplusplus } #endif diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 73b082691a3fd49..958583e66109b55 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -161,7 +161,7 @@ @MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c -@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c +@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/monitoring.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c _testcapi/hash.c _testcapi/time.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index db8817418950b92..4a04cbf63959f4b 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1769,6 +1769,9 @@ module_exec(PyObject *module) if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { return 1; } + if (_PyTestInternalCapi_Init_Monitoring(module) < 0) { + return 1; + } Py_ssize_t sizeof_gc_head = 0; #ifndef Py_GIL_DISABLED diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c new file mode 100644 index 000000000000000..800c4b9e46a6c11 --- /dev/null +++ b/Modules/_testinternalcapi/monitoring.c @@ -0,0 +1,304 @@ +#include "parts.h" +#include "../_testcapi/util.h" // NULLABLE, RETURN_INT + +#include "pycore_instruments.h" + + +static PyObject * +fire_event_py_start(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyStartEvent(&state, codelike, offset)); +} + +static PyObject * +fire_event_py_resume(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyResumeEvent(&state, codelike, offset)); +} + +static PyObject * +fire_event_py_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval)); +} + +static PyObject * +fire_event_py_yield(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval)); +} + +static PyObject * +fire_event_py_call(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyCallEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_call(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_line(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *lineno; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &lineno)) { + return NULL; + } + NULLABLE(lineno); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireLineEvent(&state, codelike, offset, lineno)); +} + +static PyObject * +fire_event_instruction(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + return NULL; + } + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireInstructionEvent(&state, codelike, offset)); +} + +static PyObject * +fire_event_jump(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + return NULL; + } + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset)); +} + +static PyObject * +fire_event_branch(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + return NULL; + } + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset)); +} + +static PyObject * +fire_event_c_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireCReturnEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_py_throw(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_reraise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_exception_handled(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_c_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireCRaiseEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_py_unwind(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_stop_iteration(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception)); +} + +static PyMethodDef TestMethods[] = { + {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, + {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, + {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, + {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, + {"fire_event_py_call", fire_event_py_call, METH_VARARGS}, + {"fire_event_call", fire_event_call, METH_VARARGS}, + {"fire_event_line", fire_event_line, METH_VARARGS}, + {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, + {"fire_event_jump", fire_event_jump, METH_VARARGS}, + {"fire_event_branch", fire_event_branch, METH_VARARGS}, + {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, + {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, + {"fire_event_raise", fire_event_raise, METH_VARARGS}, + {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, + {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, + {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, + {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, + {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestInternalCapi_Init_Monitoring(PyObject *m) +{ + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h index 49a1395f499fc3f..f8a8ab695ee1457 100644 --- a/Modules/_testinternalcapi/parts.h +++ b/Modules/_testinternalcapi/parts.h @@ -14,5 +14,6 @@ int _PyTestInternalCapi_Init_Lock(PyObject *module); int _PyTestInternalCapi_Init_PyTime(PyObject *module); int _PyTestInternalCapi_Init_Set(PyObject *module); int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); +int _PyTestInternalCapi_Init_Monitoring(PyObject *module); #endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 6f1bc2e0a107df5..e3b99e0d2e720fb 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2276,3 +2276,276 @@ PyObject *_Py_CreateMonitoringObject(void) Py_DECREF(mod); return NULL; } + + +static int +capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject **args, Py_ssize_t nargs, int event) +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyInterpreterState *interp = tstate->interp; + + uint8_t tools = state->active; + assert(args[1] == NULL); + args[1] = codelike; + PyObject *offset_obj = PyLong_FromLong(offset); + if (offset_obj == NULL) { + return -1; + } + assert(args[2] == NULL); + args[2] = offset_obj; + Py_ssize_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET; + PyObject **callargs = &args[1]; + int err = 0; + + while (tools) { + int tool = most_significant_bit(tools); + assert(tool >= 0 && tool < 8); + assert(tools & (1 << tool)); + tools ^= (1 << tool); + int res = call_one_instrument(interp, tstate, callargs, nargsf, tool, event); + if (res == 0) { + /* Nothing to do */ + } + else if (res < 0) { + /* error */ + err = -1; + break; + } + else { + /* DISABLE */ + if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + PyErr_Format(PyExc_ValueError, + "Cannot disable %s events. Callback removed.", + event_names[event]); + /* Clear tool to prevent infinite loop */ + Py_CLEAR(interp->monitoring_callables[tool][event]); + err = -1; + break; + } + else { + state->opaque &= ~(1 << tool); + } + } + } + return err; +} + +void +_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) +{ +} + +int +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[3] = { NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_PY_START); +} + +int +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[3] = { NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_PY_RESUME); +} + +int +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* retval) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { retval, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_RETURN); +} + +int +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* retval) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { retval, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_YIELD); +} + +int +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_CALL); +} + +int +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_CALL); +} + +int +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { lineno, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_LINE); +} + +int +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[3] = { NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_INSTRUCTION); +} + +int +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_JUMP); +} + +int +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_BRANCH); +} + +int +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_C_RETURN); +} + +int +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_THROW); +} + +int +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RAISE); +} + +int +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RERAISE); +} + +int +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_EXCEPTION_HANDLED); +} + +int +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_C_RAISE); +} + +int +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_UNWIND); +} + +int +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_STOP_ITERATION); +} From 1b9487c752601ff77aab9c1365bff9956406c44e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 6 Mar 2024 21:58:13 +0000 Subject: [PATCH 02/79] remove unnecessary events and add a basic test --- Lib/test/test_monitoring.py | 60 ++++++++++++++++++++ Modules/_testinternalcapi/monitoring.c | 77 ++------------------------ Python/instrumentation.c | 72 +++++------------------- 3 files changed, 79 insertions(+), 130 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index b02795903f6d175..f6a1eabc76f0589 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -9,6 +9,7 @@ import types import unittest import asyncio +import _testinternalcapi from test.support import requires_specialization PAIR = (0,1) @@ -1858,3 +1859,62 @@ def test_func(recorder): sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) sys.monitoring.set_events(TEST_TOOL, 0) self.assertGreater(len(events), 250) + + +class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): + + def setUp(self): + super(TestCApiEventGeneration, self).setUp() + + def cb(*args): + self.results.append(('cb',) + args) + + def cb2(*args): + self.results.append(('cb2',) + args) + + self.cb = cb + self.cb2 = cb2 + + events = sys.monitoring.events + capi = _testinternalcapi + self.cases = [ + # (Event, function, *args) + (events.PY_START, capi.fire_event_py_start), + (events.PY_RESUME, capi.fire_event_py_resume), + (events.PY_RETURN, capi.fire_event_py_return, 10), + (events.PY_YIELD, capi.fire_event_py_yield, 20), + (events.CALL, capi.fire_event_call, callable, 30), + (events.LINE, capi.fire_event_line, 40), + (events.JUMP, capi.fire_event_jump, 50), + (events.BRANCH, capi.fire_event_branch, 60), + (events.PY_THROW, capi.fire_event_py_throw, ValueError(1)), + (events.RAISE, capi.fire_event_raise, ValueError(2)), + (events.RERAISE, capi.fire_event_reraise, ValueError(3)), + (events.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), + (events.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), + (events.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), + ] + + def do_test(self, event, expected): + + self.results = [] + # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL + sys.monitoring.register_callback(TEST_TOOL, event, self.cb) + sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) + active = 1 << TEST_TOOL + + try: + # fire one of each event type + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) + + self.assertEqual(self.results, [('cb',) + expected]) + finally: + sys.monitoring.register_callback(TEST_TOOL, event, None) + sys.monitoring.register_callback(TEST_TOOL2, event, None) + + def test_fire_event_py_start(self): + for offset, (event, function, *args) in enumerate(self.cases): + with self.subTest(event): + output = (function.__name__, offset, *args) + self.do_test(event, output) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 800c4b9e46a6c11..5b3ce297d7ad05c 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -62,22 +62,6 @@ fire_event_py_yield(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval)); } -static PyObject * -fire_event_py_call(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { - return NULL; - } - NULLABLE(callable); - NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyCallEvent(&state, codelike, offset, callable, arg0)); -} - static PyObject * fire_event_call(PyObject *self, PyObject *args) { @@ -109,19 +93,6 @@ fire_event_line(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FireLineEvent(&state, codelike, offset, lineno)); } -static PyObject * -fire_event_instruction(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { - return NULL; - } - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireInstructionEvent(&state, codelike, offset)); -} - static PyObject * fire_event_jump(PyObject *self, PyObject *args) { @@ -150,22 +121,6 @@ fire_event_branch(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset)); } -static PyObject * -fire_event_c_return(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { - return NULL; - } - NULLABLE(callable); - NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireCReturnEvent(&state, codelike, offset, callable, arg0)); -} - static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { @@ -173,7 +128,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -188,7 +143,7 @@ fire_event_raise(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -203,7 +158,7 @@ fire_event_reraise(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -218,7 +173,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -226,22 +181,6 @@ fire_event_exception_handled(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception)); } -static PyObject * -fire_event_c_raise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { - return NULL; - } - NULLABLE(callable); - NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireCRaiseEvent(&state, codelike, offset, callable, arg0)); -} - static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { @@ -249,7 +188,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -264,7 +203,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -277,18 +216,14 @@ static PyMethodDef TestMethods[] = { {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, - {"fire_event_py_call", fire_event_py_call, METH_VARARGS}, {"fire_event_call", fire_event_call, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, - {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, {"fire_event_branch", fire_event_branch, METH_VARARGS}, - {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, {"fire_event_raise", fire_event_raise, METH_VARARGS}, {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, - {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, {NULL}, diff --git a/Python/instrumentation.c b/Python/instrumentation.c index e3b99e0d2e720fb..7f0b7f0e248c4b0 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2286,6 +2286,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t PyInterpreterState *interp = tstate->interp; uint8_t tools = state->active; +if (args[1]) _PyObject_Dump(args[1]); assert(args[1] == NULL); args[1] = codelike; PyObject *offset_obj = PyLong_FromLong(offset); @@ -2366,7 +2367,7 @@ _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, ui if (!state->active) { return 0; } - PyObject *args[4] = { retval, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_RETURN); } @@ -2378,23 +2379,11 @@ _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uin if (!state->active) { return 0; } - PyObject *args[4] = { retval, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_YIELD); } -int -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject* callable, PyObject *arg0) -{ - if (!state->active) { - return 0; - } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 4, - PY_MONITORING_EVENT_CALL); -} - int _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) @@ -2402,7 +2391,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32 if (!state->active) { return 0; } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + PyObject *args[5] = { NULL, NULL, NULL, callable, arg0 }; return capi_call_instrumentation(state, codelike, offset, args, 4, PY_MONITORING_EVENT_CALL); } @@ -2414,22 +2403,11 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32 if (!state->active) { return 0; } - PyObject *args[4] = { lineno, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, lineno }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_LINE); } -int -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) -{ - if (!state->active) { - return 0; - } - PyObject *args[3] = { NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 2, - PY_MONITORING_EVENT_INSTRUCTION); -} - int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) @@ -2437,7 +2415,7 @@ _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32 if (!state->active) { return 0; } - PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_JUMP); } @@ -2449,23 +2427,11 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint if (!state->active) { return 0; } - PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_BRANCH); } -int -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0) -{ - if (!state->active) { - return 0; - } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 4, - PY_MONITORING_EVENT_C_RETURN); -} - int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) @@ -2473,7 +2439,7 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uin if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_THROW); } @@ -2485,7 +2451,7 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint3 if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RAISE); } @@ -2497,7 +2463,7 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uin if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RERAISE); } @@ -2509,23 +2475,11 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_EXCEPTION_HANDLED); } -int -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0) -{ - if (!state->active) { - return 0; - } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 4, - PY_MONITORING_EVENT_C_RAISE); -} - int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) @@ -2533,7 +2487,7 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, ui if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_UNWIND); } @@ -2545,7 +2499,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); } From 150011a08633e8feb2d526189ff1e6b1f74a4161 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 6 Mar 2024 22:56:23 +0000 Subject: [PATCH 03/79] enhance test --- Lib/test/test_monitoring.py | 60 ++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index f6a1eabc76f0589..86fb0c260d61ee4 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1895,26 +1895,52 @@ def cb2(*args): (events.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), ] - def do_test(self, event, expected): - - self.results = [] - # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - sys.monitoring.register_callback(TEST_TOOL, event, self.cb) - sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) - active = 1 << TEST_TOOL + def test_fire_event(self): + for offset, (event, function, *args) in enumerate(self.cases): + with self.subTest(event): + output = (function.__name__, offset, *args) + self.results = [] + # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL + sys.monitoring.register_callback(TEST_TOOL, event, self.cb) + sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) + active = 1 << TEST_TOOL - try: - # fire one of each event type - for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) + try: + # fire one of each event type + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) - self.assertEqual(self.results, [('cb',) + expected]) - finally: - sys.monitoring.register_callback(TEST_TOOL, event, None) - sys.monitoring.register_callback(TEST_TOOL2, event, None) + self.assertEqual(self.results, [('cb',) + output]) + finally: + sys.monitoring.register_callback(TEST_TOOL, event, None) + sys.monitoring.register_callback(TEST_TOOL2, event, None) - def test_fire_event_py_start(self): + @unittest.skip("disable not implemented yet") + def test_disable_event(self): for offset, (event, function, *args) in enumerate(self.cases): with self.subTest(event): output = (function.__name__, offset, *args) - self.do_test(event, output) + self.results = [] + # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL + def cb(*args): + self.cb(*args) + return sys.monitoring.DISABLE + + sys.monitoring.register_callback(TEST_TOOL, event, cb) + active = 1 << TEST_TOOL + + try: + # fire one of each event type + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) + self.assertEqual(self.results, [('cb',) + output]) + + # fire again - callbacks should be disabled now + self.results = [] + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) + self.assertEqual(self.results, []) + + finally: + sys.monitoring.register_callback(TEST_TOOL, event, None) + sys.monitoring.register_callback(TEST_TOOL2, event, None) From ebc36b5915da6b380fdff7fff9fb70cced0cbb75 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Mar 2024 13:48:25 +0000 Subject: [PATCH 04/79] enable disable tests. api test functions return the new 'active' value --- Lib/test/test_monitoring.py | 40 +++++++++++++----------- Modules/_testinternalcapi/monitoring.c | 42 +++++++++++++++++--------- Python/instrumentation.c | 5 ++- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 86fb0c260d61ee4..87ad0903d058fab 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1899,47 +1899,51 @@ def test_fire_event(self): for offset, (event, function, *args) in enumerate(self.cases): with self.subTest(event): output = (function.__name__, offset, *args) - self.results = [] # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL sys.monitoring.register_callback(TEST_TOOL, event, self.cb) sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) active = 1 << TEST_TOOL try: + self.results = [] # fire one of each event type for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) + res = function(function.__name__, offset, active, *args) + self.assertEqual(res, active) self.assertEqual(self.results, [('cb',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) sys.monitoring.register_callback(TEST_TOOL2, event, None) - @unittest.skip("disable not implemented yet") def test_disable_event(self): + events = sys.monitoring.events + cannot_disable = { events.PY_THROW, events.RAISE, events.RERAISE, + events.EXCEPTION_HANDLED, events.PY_UNWIND } + + def cb_disable(*args): + self.cb(*args) + return sys.monitoring.DISABLE + for offset, (event, function, *args) in enumerate(self.cases): - with self.subTest(event): + with self.subTest(function.__name__): output = (function.__name__, offset, *args) - self.results = [] - # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - def cb(*args): - self.cb(*args) - return sys.monitoring.DISABLE - sys.monitoring.register_callback(TEST_TOOL, event, cb) + sys.monitoring.register_callback(TEST_TOOL, event, cb_disable) active = 1 << TEST_TOOL try: # fire one of each event type - for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) - self.assertEqual(self.results, [('cb',) + output]) - - # fire again - callbacks should be disabled now self.results = [] - for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) - self.assertEqual(self.results, []) + for offset, (f_event, function, *args) in enumerate(self.cases): + if f_event == event and f_event in cannot_disable: + with self.assertRaises(ValueError): + res = function(function.__name__, offset, active, *args) + self.assertEqual(res, active) + else: + res = function(function.__name__, offset, active, *args) + self.assertEqual(res, 0 if f_event == event else active) + self.assertEqual(self.results, [('cb',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 5b3ce297d7ad05c..6b0e743a2b18607 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -15,7 +15,8 @@ fire_event_py_start(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyStartEvent(&state, codelike, offset)); + int res = _PyMonitoring_FirePyStartEvent(&state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -29,7 +30,8 @@ fire_event_py_resume(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyResumeEvent(&state, codelike, offset)); + int res = _PyMonitoring_FirePyResumeEvent(&state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -44,7 +46,8 @@ fire_event_py_return(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval)); + int res = _PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -59,7 +62,8 @@ fire_event_py_yield(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval)); + int res = _PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -75,7 +79,8 @@ fire_event_call(PyObject *self, PyObject *args) NULLABLE(callable); NULLABLE(arg0); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0)); + int res = _PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -90,7 +95,8 @@ fire_event_line(PyObject *self, PyObject *args) } NULLABLE(lineno); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireLineEvent(&state, codelike, offset, lineno)); + int res = _PyMonitoring_FireLineEvent(&state, codelike, offset, lineno); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -104,7 +110,8 @@ fire_event_jump(PyObject *self, PyObject *args) return NULL; } PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset)); + int res = _PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -118,7 +125,8 @@ fire_event_branch(PyObject *self, PyObject *args) return NULL; } PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset)); + int res = _PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -133,7 +141,8 @@ fire_event_py_throw(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -148,7 +157,8 @@ fire_event_raise(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -163,7 +173,8 @@ fire_event_reraise(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -178,7 +189,8 @@ fire_event_exception_handled(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -193,7 +205,8 @@ fire_event_py_unwind(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -208,7 +221,8 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyMethodDef TestMethods[] = { diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 7f0b7f0e248c4b0..c3fe37ec17b3737 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2286,7 +2286,6 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t PyInterpreterState *interp = tstate->interp; uint8_t tools = state->active; -if (args[1]) _PyObject_Dump(args[1]); assert(args[1] == NULL); args[1] = codelike; PyObject *offset_obj = PyLong_FromLong(offset); @@ -2317,7 +2316,7 @@ if (args[1]) _PyObject_Dump(args[1]); /* DISABLE */ if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { PyErr_Format(PyExc_ValueError, - "Cannot disable %s events. Callback removed.", + "Cannot disable %s events. Callback removed.", event_names[event]); /* Clear tool to prevent infinite loop */ Py_CLEAR(interp->monitoring_callables[tool][event]); @@ -2325,7 +2324,7 @@ if (args[1]) _PyObject_Dump(args[1]); break; } else { - state->opaque &= ~(1 << tool); + state->active &= ~(1 << tool); } } } From 34179c1d83b146be9d06872adab76d446082b187 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Mar 2024 15:44:05 +0000 Subject: [PATCH 05/79] update PCbuild --- PCbuild/_testinternalcapi.vcxproj | 1 + PCbuild/_testinternalcapi.vcxproj.filters | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index a825cac9138674a..f9b8c3f3fd97d18 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -98,6 +98,7 @@ + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index abfeeb39630daf6..4347789b4715c56 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -21,10 +21,13 @@ Source Files + + Source Files + Resource Files - \ No newline at end of file + From 3c9f8bb706041c41fc492124aaf58011f3d89b50 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Mar 2024 17:32:37 +0000 Subject: [PATCH 06/79] use int --- Modules/_testinternalcapi/monitoring.c | 42 +++++++++----------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 6b0e743a2b18607..08efae39c5b303d 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -8,8 +8,7 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { return NULL; } @@ -23,8 +22,7 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { return NULL; } @@ -38,8 +36,7 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *retval; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { return NULL; @@ -54,8 +51,7 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *retval; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { return NULL; @@ -70,8 +66,7 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *callable, *arg0; if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { return NULL; @@ -87,8 +82,7 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *lineno; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &lineno)) { return NULL; @@ -103,8 +97,7 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; @@ -118,8 +111,7 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; @@ -133,8 +125,7 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -149,8 +140,7 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -165,8 +155,7 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -181,8 +170,7 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -197,8 +185,7 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -213,8 +200,7 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; From 344fd265f753f886bb604218b5edf1c94b87da94 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 11 Mar 2024 09:02:13 +0000 Subject: [PATCH 07/79] implement _PyMonitoringScopeBegin and add CodeLike type --- Modules/_testinternalcapi/monitoring.c | 128 +++++++++++++++++++++++++ Python/instrumentation.c | 11 +++ 2 files changed, 139 insertions(+) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 08efae39c5b303d..ff411027acb4e90 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -211,6 +211,126 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state.active); } +typedef struct { + PyObject_HEAD + PyMonitoringState *monitoring_states; + uint64_t version; + int num_events; + /* Other fields */ +} PyCodeLikeObject; + + +static PyObject * +CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int num_events; + if (!PyArg_ParseTuple(args, "i", &num_events)) { + return NULL; + } + PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( + num_events, sizeof(PyMonitoringState)); + if (states == NULL) { + return NULL; + } + PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->version = 0; + self->monitoring_states = states; + self->num_events = num_events; + } + else { + PyMem_Free(states); + } + return (PyObject *) self; +} + +static void +CodeLike_dealloc(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyMem_Free(self->monitoring_states); + } + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +CodeLike_str(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyObject *res = NULL; + PyObject *sep = NULL; + PyObject *parts = NULL; + + parts = PyList_New(0); + if (parts == NULL) { + goto end; + } + + PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); + if (heading == NULL) { + goto end; + } + int err = PyList_Append(parts, heading); + Py_DECREF(heading); + if (err < 0) { + goto end; + } + + for (int i = 0; i < self->num_events; i++) { + PyObject *part = PyUnicode_FromFormat("(active=%dl, opaque=%dl)", + self->monitoring_states[i].active, + self->monitoring_states[i].opaque); + if (part == NULL) { + goto end; + } + int err = PyList_Append(parts, part); + Py_XDECREF(part); + if (err < 0) { + goto end; + } + } + sep = PyUnicode_FromString(" "); + if (sep == NULL) { + goto end; + } + res = PyUnicode_Join(sep, parts); +end: + Py_XDECREF(sep); + Py_XDECREF(parts); + return res; + } + else { + return PyUnicode_FromString("PyCodeLikeObject"); + } +} + +static PyTypeObject PyCodeLike_Type = { + .ob_base = PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "monitoring.CodeLike", + .tp_doc = PyDoc_STR("CodeLike objects"), + .tp_basicsize = sizeof(PyCodeLikeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = CodeLike_new, + .tp_dealloc = (destructor) CodeLike_dealloc, + .tp_str = (reprfunc) CodeLike_str, +}; + +static PyObject * +enter_scope_py_start_py_return(PyObject *self, PyObject *args) +{ + PyObject *codelike_obj; + if (!PyArg_ParseTuple(args, "O", &codelike_obj)) { + return NULL; + } + PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; + + uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; + _PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); + + Py_RETURN_NONE; +} + static PyMethodDef TestMethods[] = { {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, @@ -226,12 +346,20 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, + {"enter_scope_py_start_py_return", enter_scope_py_start_py_return, METH_VARARGS}, {NULL}, }; int _PyTestInternalCapi_Init_Monitoring(PyObject *m) { + if (PyType_Ready(&PyCodeLike_Type) < 0) { + return NULL; + } + if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { + Py_DECREF(m); + return NULL; + } if (PyModule_AddFunctions(m, TestMethods) < 0) { return -1; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index f0e519c1986e15c..955747d8ca376da 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2343,6 +2343,17 @@ void _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (global_version(interp) == *version) { + return; + } + + _Py_GlobalMonitors *m = &interp->monitors; + for (uint32_t i = 0; i < length; i++) { + state_array[i].active = m->tools[event_types[i]]; + state_array[i].opaque = m->tools[event_types[i]]; + } + *version = global_version(interp); } int From ecaee5e8e4f6f7b5912c6d4cfa6ea02ecdb003a0 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 11 Mar 2024 22:43:04 +0000 Subject: [PATCH 08/79] more tests --- Lib/test/test_monitoring.py | 84 ++++-- Modules/_testinternalcapi/monitoring.c | 351 ++++++++++++++----------- 2 files changed, 266 insertions(+), 169 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 3c3df1f8038c01a..8b7687f291a9290 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1877,14 +1877,14 @@ class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): def setUp(self): super(TestCApiEventGeneration, self).setUp() - def cb(*args): - self.results.append(('cb',) + args) + self.codelike = _testinternalcapi.CodeLike(2) - def cb2(*args): - self.results.append(('cb2',) + args) + def cb(name, args): + self.results.append((name,) + args) - self.cb = cb - self.cb2 = cb2 + self.cb1 = lambda codelike, *args : cb('cb1', args) + self.cb2 = lambda codelike, *args : cb('cb2', args) + self.cb3 = lambda codelike, *args : cb('cb3', args) events = sys.monitoring.events capi = _testinternalcapi @@ -1907,22 +1907,28 @@ def cb2(*args): ] def test_fire_event(self): - for offset, (event, function, *args) in enumerate(self.cases): + for event, function, *args in self.cases: + offset = 0 + self.codelike = _testinternalcapi.CodeLike(2) with self.subTest(event): - output = (function.__name__, offset, *args) + output = (offset, *args) # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - sys.monitoring.register_callback(TEST_TOOL, event, self.cb) + sys.monitoring.register_callback(TEST_TOOL, event, self.cb1) sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) active = 1 << TEST_TOOL try: self.results = [] # fire one of each event type - for offset, (_, function, *args) in enumerate(self.cases): - res = function(function.__name__, offset, active, *args) - self.assertEqual(res, active) - - self.assertEqual(self.results, [('cb',) + output]) + for _, function, *args in self.cases: + res = function(self.codelike, offset, active, *args) + try: + self.assertEqual(res, active) + except: + breakpoint() + raise + + self.assertEqual(self.results, [('cb1',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) sys.monitoring.register_callback(TEST_TOOL2, event, None) @@ -1933,12 +1939,14 @@ def test_disable_event(self): events.EXCEPTION_HANDLED, events.PY_UNWIND } def cb_disable(*args): - self.cb(*args) + self.cb1(*args) return sys.monitoring.DISABLE - for offset, (event, function, *args) in enumerate(self.cases): + for event, function, *args in self.cases: + offset = 1 + self.codelike = _testinternalcapi.CodeLike(2) with self.subTest(function.__name__): - output = (function.__name__, offset, *args) + output = (offset, *args) sys.monitoring.register_callback(TEST_TOOL, event, cb_disable) active = 1 << TEST_TOOL @@ -1946,16 +1954,48 @@ def cb_disable(*args): try: # fire one of each event type self.results = [] - for offset, (f_event, function, *args) in enumerate(self.cases): + for f_event, function, *args in self.cases: if f_event == event and f_event in cannot_disable: with self.assertRaises(ValueError): - res = function(function.__name__, offset, active, *args) - self.assertEqual(res, active) + res = function(self.codelike, offset, active, *args) + try: + self.assertEqual(res, active) + except: + breakpoint() + raise else: - res = function(function.__name__, offset, active, *args) + res = function(self.codelike, offset, active, *args) self.assertEqual(res, 0 if f_event == event else active) - self.assertEqual(self.results, [('cb',) + output]) + self.assertEqual(self.results, [('cb1',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) sys.monitoring.register_callback(TEST_TOOL2, event, None) + + def test_enter_scope(self): + events = sys.monitoring.events + capi = _testinternalcapi + + cl = _testinternalcapi.CodeLike(2) + capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] + + sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) + + self.results = [] + capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) + capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) + self.assertEqual(self.results, [('cb1', 0)]) + + sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_RETURN, self.cb2) + + self.results = [] + capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) + capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) + self.assertEqual(self.results, [('cb1', 0), ('cb2', 1, 42)]) + + sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, None) + + self.results = [] + capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) + capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) + self.assertEqual(self.results, [('cb2', 1, 42)]) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index ff411027acb4e90..7094acad3be7f1f 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -3,6 +3,109 @@ #include "pycore_instruments.h" +typedef struct { + PyObject_HEAD + PyMonitoringState *monitoring_states; + uint64_t version; + int num_events; + /* Other fields */ +} PyCodeLikeObject; + + +static PyObject * +CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int num_events; + if (!PyArg_ParseTuple(args, "i", &num_events)) { + return NULL; + } + PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( + num_events, sizeof(PyMonitoringState)); + if (states == NULL) { + return NULL; + } + PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->version = 0; + self->monitoring_states = states; + self->num_events = num_events; + } + else { + PyMem_Free(states); + } + return (PyObject *) self; +} + +static void +CodeLike_dealloc(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyMem_Free(self->monitoring_states); + } + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +CodeLike_str(PyCodeLikeObject *self) +{ + PyObject *res = NULL; + PyObject *sep = NULL; + PyObject *parts = NULL; + if (self->monitoring_states) { + parts = PyList_New(0); + if (parts == NULL) { + goto end; + } + + PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); + if (heading == NULL) { + goto end; + } + int err = PyList_Append(parts, heading); + Py_DECREF(heading); + if (err < 0) { + goto end; + } + + for (int i = 0; i < self->num_events; i++) { + PyObject *part = PyUnicode_FromFormat("(active=%d, opaque=%d)", + self->monitoring_states[i].active, + self->monitoring_states[i].opaque); + if (part == NULL) { + goto end; + } + int err = PyList_Append(parts, part); + Py_XDECREF(part); + if (err < 0) { + goto end; + } + } + sep = PyUnicode_FromString(": "); + if (sep == NULL) { + goto end; + } + res = PyUnicode_Join(sep, parts); + } +end: + Py_XDECREF(sep); + Py_XDECREF(parts); + return res; +} + +static PyTypeObject PyCodeLike_Type = { + .ob_base = PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "monitoring.CodeLike", + .tp_doc = PyDoc_STR("CodeLike objects"), + .tp_basicsize = sizeof(PyCodeLikeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = CodeLike_new, + .tp_dealloc = (destructor) CodeLike_dealloc, + .tp_str = (reprfunc) CodeLike_str, +}; + + +/*******************************************************************/ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) @@ -13,9 +116,13 @@ fire_event_py_start(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyStartEvent(&state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyStartEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -27,9 +134,13 @@ fire_event_py_resume(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyResumeEvent(&state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyResumeEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -42,9 +153,13 @@ fire_event_py_return(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -57,9 +172,13 @@ fire_event_py_yield(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -71,11 +190,15 @@ fire_event_call(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { return NULL; } - NULLABLE(callable); + NULLABLE(codelike); NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -88,9 +211,13 @@ fire_event_line(PyObject *self, PyObject *args) return NULL; } NULLABLE(lineno); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireLineEvent(&state, codelike, offset, lineno); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -102,9 +229,13 @@ fire_event_jump(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; } - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -116,9 +247,13 @@ fire_event_branch(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; } - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -131,9 +266,13 @@ fire_event_py_throw(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -146,9 +285,13 @@ fire_event_raise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -161,9 +304,13 @@ fire_event_reraise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -176,9 +323,13 @@ fire_event_exception_handled(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -191,9 +342,13 @@ fire_event_py_unwind(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -206,115 +361,17 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); -} - -typedef struct { - PyObject_HEAD - PyMonitoringState *monitoring_states; - uint64_t version; - int num_events; - /* Other fields */ -} PyCodeLikeObject; - - -static PyObject * -CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - int num_events; - if (!PyArg_ParseTuple(args, "i", &num_events)) { - return NULL; - } - PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( - num_events, sizeof(PyMonitoringState)); - if (states == NULL) { - return NULL; - } - PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); - if (self != NULL) { - self->version = 0; - self->monitoring_states = states; - self->num_events = num_events; - } - else { - PyMem_Free(states); - } - return (PyObject *) self; -} - -static void -CodeLike_dealloc(PyCodeLikeObject *self) -{ - if (self->monitoring_states) { - PyMem_Free(self->monitoring_states); - } - Py_TYPE(self)->tp_free((PyObject *) self); -} - -static PyObject * -CodeLike_str(PyCodeLikeObject *self) -{ - if (self->monitoring_states) { - PyObject *res = NULL; - PyObject *sep = NULL; - PyObject *parts = NULL; - - parts = PyList_New(0); - if (parts == NULL) { - goto end; - } - PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); - if (heading == NULL) { - goto end; - } - int err = PyList_Append(parts, heading); - Py_DECREF(heading); - if (err < 0) { - goto end; - } + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; - for (int i = 0; i < self->num_events; i++) { - PyObject *part = PyUnicode_FromFormat("(active=%dl, opaque=%dl)", - self->monitoring_states[i].active, - self->monitoring_states[i].opaque); - if (part == NULL) { - goto end; - } - int err = PyList_Append(parts, part); - Py_XDECREF(part); - if (err < 0) { - goto end; - } - } - sep = PyUnicode_FromString(" "); - if (sep == NULL) { - goto end; - } - res = PyUnicode_Join(sep, parts); -end: - Py_XDECREF(sep); - Py_XDECREF(parts); - return res; - } - else { - return PyUnicode_FromString("PyCodeLikeObject"); - } + int res = _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } -static PyTypeObject PyCodeLike_Type = { - .ob_base = PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "monitoring.CodeLike", - .tp_doc = PyDoc_STR("CodeLike objects"), - .tp_basicsize = sizeof(PyCodeLikeObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = CodeLike_new, - .tp_dealloc = (destructor) CodeLike_dealloc, - .tp_str = (reprfunc) CodeLike_str, -}; +/*******************************************************************/ static PyObject * enter_scope_py_start_py_return(PyObject *self, PyObject *args) @@ -354,11 +411,11 @@ int _PyTestInternalCapi_Init_Monitoring(PyObject *m) { if (PyType_Ready(&PyCodeLike_Type) < 0) { - return NULL; + return -1; } if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { Py_DECREF(m); - return NULL; + return -1; } if (PyModule_AddFunctions(m, TestMethods) < 0) { return -1; From 5c68095e2c555877bfa843dd3d229e2a349dd53a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 12 Mar 2024 23:30:39 +0000 Subject: [PATCH 09/79] make functions public --- Include/cpython/monitoring.h | 82 ++++++++ Include/internal/pycore_instruments.h | 83 -------- Include/monitoring.h | 276 +++++++++++++++++++++++++ Makefile.pre.in | 2 + Modules/_testinternalcapi/monitoring.c | 34 +-- Python/instrumentation.c | 194 +++++++++++++---- 6 files changed, 530 insertions(+), 141 deletions(-) create mode 100644 Include/cpython/monitoring.h create mode 100644 Include/monitoring.h diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h new file mode 100644 index 000000000000000..aa718e1113a1a90 --- /dev/null +++ b/Include/cpython/monitoring.h @@ -0,0 +1,82 @@ +#ifndef Py_CPYTHON_MONITORING_H +# error "this header file must not be included directly" +#endif + +void +_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); + +int +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +int +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +int +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +int +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +int +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + +int +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + + +int +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); + +int +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +int +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +int +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +int +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +int +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +int +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +int +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 7be351e273e35ff..7f84d4a763bbcf6 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -101,89 +101,6 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index); extern PyObject _PyInstrumentation_MISSING; extern PyObject _PyInstrumentation_DISABLE; -typedef struct _PyMonitoringState { - uint8_t active; - uint8_t opaque; -} PyMonitoringState; - - -/*** C API ***/ - -PyAPI_FUNC(void) -_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *retval); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *retval); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject* callable, PyObject *arg0); - -PyAPI_FUNC(int) -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject* callable, PyObject *arg0); - - -PyAPI_FUNC(int) -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *lineno); - -PyAPI_FUNC(int) -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - - -PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - #ifdef __cplusplus } #endif diff --git a/Include/monitoring.h b/Include/monitoring.h new file mode 100644 index 000000000000000..d6a1a6c4e7033ce --- /dev/null +++ b/Include/monitoring.h @@ -0,0 +1,276 @@ +#ifndef Py_MONITORING_H +#define Py_MONITORING_H +#ifdef __cplusplus +extern "C" { + +#endif + +typedef struct _PyMonitoringState { + uint8_t active; + uint8_t opaque; +} PyMonitoringState; + + +#ifndef Py_LIMITED_API +# define Py_CPYTHON_MONITORING_H +# include "cpython/monitoring.h" +# undef Py_CPYTHON_MONITORING_H + +#define IF_ACTIVE(X) \ + if (state->active) { \ + return (X); \ + } \ + else { \ + return 0; \ + } + +#endif + + +#ifndef Py_LIMITED_API +static inline void +PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) +{ + _PyMonitoringScopeBegin(state_array, version, event_types, length); +} +#else +extern void +PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); +#endif + + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); +} +#else +extern int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +#endif + + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); +} +#else +extern int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); +} +#else +extern int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); +} +#else +extern int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno) +{ + IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); +} +#else +extern int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); +} +#else +extern int +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} +#else +extern int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); +} +#else +extern int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MONITORING_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index b1aaa594c9f6efb..21057d9c17d36b9 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -989,6 +989,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/methodobject.h \ $(srcdir)/Include/modsupport.h \ $(srcdir)/Include/moduleobject.h \ + $(srcdir)/Include/monitoring.h \ $(srcdir)/Include/object.h \ $(srcdir)/Include/objimpl.h \ $(srcdir)/Include/opcode.h \ @@ -1059,6 +1060,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/longobject.h \ $(srcdir)/Include/cpython/memoryobject.h \ $(srcdir)/Include/cpython/methodobject.h \ + $(srcdir)/Include/cpython/monitoring.h \ $(srcdir)/Include/cpython/object.h \ $(srcdir)/Include/cpython/objimpl.h \ $(srcdir)/Include/cpython/odictobject.h \ diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 7094acad3be7f1f..26ce0e1bc0f67a4 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -1,7 +1,9 @@ #include "parts.h" #include "../_testcapi/util.h" // NULLABLE, RETURN_INT -#include "pycore_instruments.h" +#include "monitoring.h" + +#include "internal/pycore_instruments.h" typedef struct { PyObject_HEAD @@ -121,7 +123,7 @@ fire_event_py_start(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyStartEvent(state, codelike, offset); + int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -139,7 +141,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyResumeEvent(state, codelike, offset); + int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -158,7 +160,7 @@ fire_event_py_return(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -177,7 +179,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -197,7 +199,7 @@ fire_event_call(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); RETURN_INT(res == -1 ? -1 : state->active); } @@ -216,7 +218,7 @@ fire_event_line(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); RETURN_INT(res == -1 ? -1 : state->active); } @@ -234,7 +236,7 @@ fire_event_jump(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -252,7 +254,7 @@ fire_event_branch(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -271,7 +273,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -290,7 +292,7 @@ fire_event_raise(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -309,7 +311,7 @@ fire_event_reraise(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -328,7 +330,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -347,7 +349,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -367,7 +369,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -383,7 +385,7 @@ enter_scope_py_start_py_return(PyObject *self, PyObject *args) PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; - _PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); + PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); Py_RETURN_NONE; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 955747d8ca376da..1520931e386d45e 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1,5 +1,6 @@ #include "Python.h" +#include "monitoring.h" #include "opcode_ids.h" #include "pycore_bitutils.h" // _Py_popcount32 @@ -2359,9 +2360,7 @@ _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, int _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; return capi_call_instrumentation(state, codelike, offset, args, 2, PY_MONITORING_EVENT_PY_START); @@ -2370,21 +2369,19 @@ _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uin int _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; return capi_call_instrumentation(state, codelike, offset, args, 2, PY_MONITORING_EVENT_PY_RESUME); } + + int _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* retval) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_RETURN); @@ -2394,9 +2391,7 @@ int _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* retval) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_YIELD); @@ -2406,9 +2401,7 @@ int _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[5] = { NULL, NULL, NULL, callable, arg0 }; return capi_call_instrumentation(state, codelike, offset, args, 4, PY_MONITORING_EVENT_CALL); @@ -2418,9 +2411,7 @@ int _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *lineno) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, lineno }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_LINE); @@ -2430,9 +2421,7 @@ int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_JUMP); @@ -2442,9 +2431,7 @@ int _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_BRANCH); @@ -2454,9 +2441,7 @@ int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_THROW); @@ -2466,9 +2451,7 @@ int _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RAISE); @@ -2478,9 +2461,7 @@ int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RERAISE); @@ -2490,9 +2471,7 @@ int _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_EXCEPTION_HANDLED); @@ -2502,9 +2481,7 @@ int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_UNWIND); @@ -2514,10 +2491,143 @@ int _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); } + + + +#ifdef Py_LIMITED_API +void +PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) +{ + _PyMonitoringScopeBegin(state_array, version, event_types, length); +} + +int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); +} + +int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); +} + +int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); +} + +int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); +} + +int +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); +{ + IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); +} + +int +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); +} + +int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} + +int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} + +int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); +} + +int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +{ + IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); +} + +#endif From 7661865eba5eadd2304890af3c208e7201f13374 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 11:43:22 +0000 Subject: [PATCH 10/79] move tests from testinternalcapi to testcapi --- Include/cpython/monitoring.h | 43 +++++++++---------- Include/monitoring.h | 1 - .../monitoring.c | 5 ++- Modules/_testcapi/parts.h | 1 + Modules/_testcapimodule.c | 3 ++ Modules/_testinternalcapi.c | 3 -- Modules/_testinternalcapi/parts.h | 1 - PCbuild/_testinternalcapi.vcxproj | 1 - Python/instrumentation.c | 4 +- 9 files changed, 31 insertions(+), 31 deletions(-) rename Modules/{_testinternalcapi => _testcapi}/monitoring.c (99%) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index aa718e1113a1a90..d3e4445e199faa3 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,81 +2,80 @@ # error "this header file must not be included directly" #endif -void +PyAPI_FUNC(void) _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); + uint8_t *event_types, uint32_t length); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0); - -int +PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *lineno); -int +PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index d6a1a6c4e7033ce..d891c5c004e4720 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -26,7 +26,6 @@ typedef struct _PyMonitoringState { #endif - #ifndef Py_LIMITED_API static inline void PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testcapi/monitoring.c similarity index 99% rename from Modules/_testinternalcapi/monitoring.c rename to Modules/_testcapi/monitoring.c index 26ce0e1bc0f67a4..c1d302ac177258d 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -1,8 +1,9 @@ #include "parts.h" -#include "../_testcapi/util.h" // NULLABLE, RETURN_INT +#include "util.h" #include "monitoring.h" +#define Py_BUILD_CORE #include "internal/pycore_instruments.h" typedef struct { @@ -410,7 +411,7 @@ static PyMethodDef TestMethods[] = { }; int -_PyTestInternalCapi_Init_Monitoring(PyObject *m) +_PyTestCapi_Init_Monitoring(PyObject *m) { if (PyType_Ready(&PyCodeLike_Type) < 0) { return -1; diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index e8cfb2423500d4b..fe6b6f6eb9905aa 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -60,6 +60,7 @@ int _PyTestCapi_Init_GC(PyObject *module); int _PyTestCapi_Init_Sys(PyObject *module); int _PyTestCapi_Init_Hash(PyObject *module); int _PyTestCapi_Init_Time(PyObject *module); +int _PyTestCapi_Init_Monitoring(PyObject *module); int _PyTestCapi_Init_VectorcallLimited(PyObject *module); int _PyTestCapi_Init_HeaptypeRelative(PyObject *module); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index b03f871b089c8a3..b179e19c0372339 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4110,6 +4110,9 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_Time(m) < 0) { return NULL; } + if (_PyTestCapi_Init_Monitoring(m) < 0) { + return NULL; + } PyState_AddModule(m, &_testcapimodule); return m; diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 4a04cbf63959f4b..db8817418950b92 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1769,9 +1769,6 @@ module_exec(PyObject *module) if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { return 1; } - if (_PyTestInternalCapi_Init_Monitoring(module) < 0) { - return 1; - } Py_ssize_t sizeof_gc_head = 0; #ifndef Py_GIL_DISABLED diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h index f8a8ab695ee1457..49a1395f499fc3f 100644 --- a/Modules/_testinternalcapi/parts.h +++ b/Modules/_testinternalcapi/parts.h @@ -14,6 +14,5 @@ int _PyTestInternalCapi_Init_Lock(PyObject *module); int _PyTestInternalCapi_Init_PyTime(PyObject *module); int _PyTestInternalCapi_Init_Set(PyObject *module); int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); -int _PyTestInternalCapi_Init_Monitoring(PyObject *module); #endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index f9b8c3f3fd97d18..a825cac9138674a 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -98,7 +98,6 @@ - diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 1520931e386d45e..a6e3892671b2c98 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2342,7 +2342,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t void _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2500,6 +2500,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik #ifdef Py_LIMITED_API + void PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) @@ -2507,6 +2508,7 @@ PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, _PyMonitoringScopeBegin(state_array, version, event_types, length); } + int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { From 580a9f3a4c3a908b08ad1502c94c47893f60b6cb Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 11:52:53 +0000 Subject: [PATCH 11/79] add include --- Include/Python.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/Python.h b/Include/Python.h index 01fc45137a17bbc..f1b23855e33fbaa 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -78,6 +78,7 @@ #include "setobject.h" #include "methodobject.h" #include "moduleobject.h" +#include "monitoring.h" #include "cpython/funcobject.h" #include "cpython/classobject.h" #include "fileobject.h" From 19a1f90ba055c1c97ddba71b43e90902d6010026 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 11:53:44 +0000 Subject: [PATCH 12/79] PyMonitoringScopeBegin --> PyMonitoring_BeginScope --- Include/cpython/monitoring.h | 4 ++-- Include/monitoring.h | 10 +++++----- Modules/_sqlite/connection-dd92fcfb.o.tmp | 0 Modules/_sqlite/cursor-8e377591.o.tmp | 0 Modules/_testcapi/monitoring.c | 2 +- Python/instrumentation.c | 9 ++++----- 6 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 Modules/_sqlite/connection-dd92fcfb.o.tmp create mode 100644 Modules/_sqlite/cursor-8e377591.o.tmp diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index d3e4445e199faa3..85c9356177fa614 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -3,8 +3,8 @@ #endif PyAPI_FUNC(void) -_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); +_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index d891c5c004e4720..e39d45ac74fa871 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -28,15 +28,15 @@ typedef struct _PyMonitoringState { #ifndef Py_LIMITED_API static inline void -PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) +PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) { - _PyMonitoringScopeBegin(state_array, version, event_types, length); + _PyMonitoring_BeginScope(state_array, version, event_types, length); } #else extern void -PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); +PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); #endif diff --git a/Modules/_sqlite/connection-dd92fcfb.o.tmp b/Modules/_sqlite/connection-dd92fcfb.o.tmp new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/Modules/_sqlite/cursor-8e377591.o.tmp b/Modules/_sqlite/cursor-8e377591.o.tmp new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index c1d302ac177258d..72972b177464288 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -386,7 +386,7 @@ enter_scope_py_start_py_return(PyObject *self, PyObject *args) PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; - PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); + PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 2); Py_RETURN_NONE; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index a6e3892671b2c98..5ead3a005250a56 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1,6 +1,5 @@ #include "Python.h" -#include "monitoring.h" #include "opcode_ids.h" #include "pycore_bitutils.h" // _Py_popcount32 @@ -2341,8 +2340,8 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t } void -_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) +_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2502,10 +2501,10 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik #ifdef Py_LIMITED_API void -PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) { - _PyMonitoringScopeBegin(state_array, version, event_types, length); + _PyMonitoring_BeginScope(state_array, version, event_types, length); } From 745a2b3c33f1e7a141bd79ccaaa3d925039a1112 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 13:10:42 +0000 Subject: [PATCH 13/79] IF_ACTIVE --> _PyMonitoring_IF_ACTIVE --- Include/monitoring.h | 80 +++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/Include/monitoring.h b/Include/monitoring.h index e39d45ac74fa871..9009d4c47a865c3 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -16,8 +16,8 @@ typedef struct _PyMonitoringState { # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H -#define IF_ACTIVE(X) \ - if (state->active) { \ +#define _PyMonitoring_IF_ACTIVE(STATE, X) \ + if ((STATE)->active) { \ return (X); \ } \ else { \ @@ -44,7 +44,9 @@ PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, static inline int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } #else extern int @@ -56,7 +58,9 @@ PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint static inline int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } #else extern int @@ -68,7 +72,9 @@ static inline int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } #else extern int @@ -81,7 +87,9 @@ static inline int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } #else extern int @@ -94,7 +102,9 @@ static inline int PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -107,7 +117,9 @@ static inline int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -120,7 +132,9 @@ static inline int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *lineno) { - IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } #else extern int @@ -132,7 +146,9 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_ static inline int PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } #else extern int @@ -144,7 +160,9 @@ static inline int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } #else extern int @@ -157,7 +175,9 @@ static inline int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } #else extern int @@ -170,7 +190,9 @@ static inline int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -183,7 +205,9 @@ static inline int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } #else extern int @@ -196,7 +220,9 @@ static inline int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } #else extern int @@ -209,7 +235,9 @@ static inline int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } #else extern int @@ -222,7 +250,9 @@ static inline int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } #else extern int @@ -235,7 +265,9 @@ static inline int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -248,7 +280,9 @@ static inline int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } #else extern int @@ -261,7 +295,9 @@ static inline int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } #else extern int @@ -269,6 +305,10 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike PyObject *exception); #endif +#ifndef Py_LIMITED_API +#undef _PyMonitoring_IF_ACTIVE +#endif + #ifdef __cplusplus } #endif From ba5e7e08ed86e377d27ae5cef46cd7f756be9604 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 13:32:55 +0000 Subject: [PATCH 14/79] upate tests --- Lib/test/test_monitoring.py | 14 +++++++------- PCbuild/_testcapi.vcxproj | 1 + PCbuild/_testcapi.vcxproj.filters | 3 +++ PCbuild/_testinternalcapi.vcxproj.filters | 3 --- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 8b7687f291a9290..d777478396ec56a 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -9,7 +9,7 @@ import types import unittest import asyncio -import _testinternalcapi +import _testcapi from test import support from test.support import requires_specialization, script_helper @@ -1877,7 +1877,7 @@ class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): def setUp(self): super(TestCApiEventGeneration, self).setUp() - self.codelike = _testinternalcapi.CodeLike(2) + self.codelike = _testcapi.CodeLike(2) def cb(name, args): self.results.append((name,) + args) @@ -1887,7 +1887,7 @@ def cb(name, args): self.cb3 = lambda codelike, *args : cb('cb3', args) events = sys.monitoring.events - capi = _testinternalcapi + capi = _testcapi self.cases = [ # (Event, function, *args) (events.PY_START, capi.fire_event_py_start), @@ -1909,7 +1909,7 @@ def cb(name, args): def test_fire_event(self): for event, function, *args in self.cases: offset = 0 - self.codelike = _testinternalcapi.CodeLike(2) + self.codelike = _testcapi.CodeLike(2) with self.subTest(event): output = (offset, *args) # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL @@ -1944,7 +1944,7 @@ def cb_disable(*args): for event, function, *args in self.cases: offset = 1 - self.codelike = _testinternalcapi.CodeLike(2) + self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): output = (offset, *args) @@ -1974,9 +1974,9 @@ def cb_disable(*args): def test_enter_scope(self): events = sys.monitoring.events - capi = _testinternalcapi + capi = _testcapi - cl = _testinternalcapi.CodeLike(2) + cl = _testcapi.CodeLike(2) capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index 66df0a61b5b5a66..3e1843a5da236cd 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -128,6 +128,7 @@ + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index 651eb1d6ba0b7f3..ab3660a386a6f3d 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -111,6 +111,9 @@ Source Files + + Source Files + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index 4347789b4715c56..27429ea5833077f 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -21,9 +21,6 @@ Source Files - - Source Files - From aa19675bb85208b0e457a2c5d3875fef96221177 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 16:51:53 +0000 Subject: [PATCH 15/79] offset is int, event_types is const, remove "opaque" --- Include/cpython/monitoring.h | 40 +++++++++--------- Include/monitoring.h | 77 +++++++++++++++++----------------- Modules/_testcapi/monitoring.c | 4 +- Python/instrumentation.c | 37 ++++++++-------- 4 files changed, 79 insertions(+), 79 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 85c9356177fa614..ee8604e470cfbb6 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -4,78 +4,78 @@ PyAPI_FUNC(void) _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); + const uint8_t *event_types, uint32_t length); PyAPI_FUNC(int) -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno); PyAPI_FUNC(int) -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index 9009d4c47a865c3..b9ea22e7157613e 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -7,7 +7,6 @@ extern "C" { typedef struct _PyMonitoringState { uint8_t active; - uint8_t opaque; } PyMonitoringState; @@ -29,20 +28,20 @@ typedef struct _PyMonitoringState { #ifndef Py_LIMITED_API static inline void PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + const uint8_t *event_types, uint32_t length) { _PyMonitoring_BeginScope(state_array, version, event_types, length); } #else extern void PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); + const uint8_t *event_types, uint32_t length); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, @@ -50,13 +49,13 @@ PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, @@ -64,12 +63,12 @@ PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uin } #else extern int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { _PyMonitoring_IF_ACTIVE( @@ -78,13 +77,13 @@ PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uin } #else extern int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { _PyMonitoring_IF_ACTIVE( @@ -93,13 +92,13 @@ PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -108,13 +107,13 @@ PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint3 } #else extern int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -123,13 +122,13 @@ PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_ } #else extern int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno) { _PyMonitoring_IF_ACTIVE( @@ -138,13 +137,13 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_ } #else extern int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, @@ -152,12 +151,12 @@ PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, } #else extern int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( @@ -166,13 +165,13 @@ PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_ } #else extern int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( @@ -181,13 +180,13 @@ PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint3 } #else extern int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -196,13 +195,13 @@ PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -211,13 +210,13 @@ PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -226,13 +225,13 @@ PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32 } #else extern int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -241,13 +240,13 @@ PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -256,13 +255,13 @@ PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codel } #else extern int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -271,13 +270,13 @@ PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint3 } #else extern int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -286,13 +285,13 @@ PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uin } #else extern int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -301,7 +300,7 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike } #else extern int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 72972b177464288..2dea857c5a7762c 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -71,9 +71,7 @@ CodeLike_str(PyCodeLikeObject *self) } for (int i = 0; i < self->num_events; i++) { - PyObject *part = PyUnicode_FromFormat("(active=%d, opaque=%d)", - self->monitoring_states[i].active, - self->monitoring_states[i].opaque); + PyObject *part = PyUnicode_FromFormat(" %d", self->monitoring_states[i].active); if (part == NULL) { goto end; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5ead3a005250a56..6f0be1f9d218f2d 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2287,7 +2287,7 @@ PyObject *_Py_CreateMonitoringObject(void) static int -capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offset, PyObject **args, Py_ssize_t nargs, int event) { PyThreadState *tstate = _PyThreadState_GET(); @@ -2296,6 +2296,10 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t uint8_t tools = state->active; assert(args[1] == NULL); args[1] = codelike; + if (offset < 0) { + PyErr_SetString(PyExc_ValueError, "offset must be non-negative"); + return -1; + } PyObject *offset_obj = PyLong_FromLong(offset); if (offset_obj == NULL) { return -1; @@ -2341,7 +2345,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t void _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + const uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2351,13 +2355,12 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, _Py_GlobalMonitors *m = &interp->monitors; for (uint32_t i = 0; i < length; i++) { state_array[i].active = m->tools[event_types[i]]; - state_array[i].opaque = m->tools[event_types[i]]; } *version = global_version(interp); } int -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; @@ -2366,7 +2369,7 @@ _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; @@ -2377,7 +2380,7 @@ _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, ui int -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* retval) { assert(state->active); @@ -2387,7 +2390,7 @@ _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, ui } int -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* retval) { assert(state->active); @@ -2397,7 +2400,7 @@ _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { assert(state->active); @@ -2407,7 +2410,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32 } int -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno) { assert(state->active); @@ -2417,7 +2420,7 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32 } int -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { assert(state->active); @@ -2427,7 +2430,7 @@ _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32 } int -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { assert(state->active); @@ -2437,7 +2440,7 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint } int -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2447,7 +2450,7 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2457,7 +2460,7 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint3 } int -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2467,7 +2470,7 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2477,7 +2480,7 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code } int -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2487,7 +2490,7 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, ui } int -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); From 68aa35202812dedd382f0879ff45dbc4038076a5 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 17:36:01 +0000 Subject: [PATCH 16/79] PyMonitoring_FireLineEvent takes lineno as int --- Include/cpython/monitoring.h | 2 +- Include/monitoring.h | 4 ++-- Modules/_testcapi/monitoring.c | 6 ++---- Python/instrumentation.c | 14 ++++++++++---- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index ee8604e470cfbb6..8a42d778aafbff0 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -30,7 +30,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int of PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno); + int lineno); PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index b9ea22e7157613e..5d1f735ab83b047 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -129,7 +129,7 @@ PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int off #ifndef Py_LIMITED_API static inline int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno) + int lineno) { _PyMonitoring_IF_ACTIVE( state, @@ -138,7 +138,7 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int off #else extern int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno); + int lineno); #endif #ifndef Py_LIMITED_API diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 2dea857c5a7762c..1e1527e5838870b 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -206,12 +206,10 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; - PyObject *lineno; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &lineno)) { + int offset, active, lineno; + if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &active, &lineno)) { return NULL; } - NULLABLE(lineno); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 6f0be1f9d218f2d..375fd3f334549f3 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2411,12 +2411,18 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int of int _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno) + int lineno) { assert(state->active); - PyObject *args[4] = { NULL, NULL, NULL, lineno }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_LINE); + PyObject *lno = PyLong_FromLong(lineno); + if (lno == NULL) { + return -1; + } + PyObject *args[4] = { NULL, NULL, NULL, lno }; + int res= capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_LINE); + Py_DECREF(lno); + return res; } int From db4e3b80e7ccd5065d879bb17b7416c468182736 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 17:48:34 +0000 Subject: [PATCH 17/79] add news --- .../next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst diff --git a/Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst b/Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst new file mode 100644 index 000000000000000..e74c0397b85aa14 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst @@ -0,0 +1 @@ +Add a C-API for firing monitoring events. From 445b19fb3154368ec1e4daeedfe8b79a05bf9e1c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 18:17:37 +0000 Subject: [PATCH 18/79] remove debug stuff --- Lib/test/test_monitoring.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 82138172b827836..abb759b0431271e 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1937,11 +1937,7 @@ def test_fire_event(self): # fire one of each event type for _, function, *args in self.cases: res = function(self.codelike, offset, active, *args) - try: - self.assertEqual(res, active) - except: - breakpoint() - raise + self.assertEqual(res, active) self.assertEqual(self.results, [('cb1',) + output]) finally: @@ -1973,11 +1969,7 @@ def cb_disable(*args): if f_event == event and f_event in cannot_disable: with self.assertRaises(ValueError): res = function(self.codelike, offset, active, *args) - try: - self.assertEqual(res, active) - except: - breakpoint() - raise + self.assertEqual(res, active) else: res = function(self.codelike, offset, active, *args) self.assertEqual(res, 0 if f_event == event else active) From 33ce7aaa1b43c878832099f59a03060939acbe18 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 23:11:31 +0000 Subject: [PATCH 19/79] not static --- Modules/_testcapi/monitoring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 1e1527e5838870b..ec4a640a7f81617 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -93,7 +93,7 @@ CodeLike_str(PyCodeLikeObject *self) return res; } -static PyTypeObject PyCodeLike_Type = { +PyTypeObject PyCodeLike_Type = { .ob_base = PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "monitoring.CodeLike", .tp_doc = PyDoc_STR("CodeLike objects"), From cf6e20dad3d9dd0396f40a22d9054e0af348bc83 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 23:51:30 +0000 Subject: [PATCH 20/79] Revert "not static" This reverts commit 33ce7aaa1b43c878832099f59a03060939acbe18. --- Modules/_testcapi/monitoring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index ec4a640a7f81617..1e1527e5838870b 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -93,7 +93,7 @@ CodeLike_str(PyCodeLikeObject *self) return res; } -PyTypeObject PyCodeLike_Type = { +static PyTypeObject PyCodeLike_Type = { .ob_base = PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "monitoring.CodeLike", .tp_doc = PyDoc_STR("CodeLike objects"), From 89b05f14f496624262d7429c1759c8986b6cc07a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 14 Mar 2024 11:37:19 +0000 Subject: [PATCH 21/79] ignore PyCodeLike_Type --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 686a3d3160cc906..dc338ab0e297224 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -395,6 +395,7 @@ Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - Modules/xxsubtype.c - spamdict_type - Modules/xxsubtype.c - spamlist_type - +Modules/_testcapi/monitoring.c - PyCodeLike_Type ##----------------------- ## non-static types - initialized once From 5f727256d92574e35e7aac95c51c8506b453241b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 14 Mar 2024 13:22:14 +0000 Subject: [PATCH 22/79] typo --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index dc338ab0e297224..c01bfb3239448b7 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -395,7 +395,7 @@ Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - Modules/xxsubtype.c - spamdict_type - Modules/xxsubtype.c - spamlist_type - -Modules/_testcapi/monitoring.c - PyCodeLike_Type +Modules/_testcapi/monitoring.c - PyCodeLike_Type - ##----------------------- ## non-static types - initialized once From 6368b42c9e83c818a3a0d33444676a9853b1ef03 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 14 Mar 2024 16:50:19 +0000 Subject: [PATCH 23/79] space to tab --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index c01bfb3239448b7..ae279c0c0237d31 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -395,7 +395,7 @@ Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - Modules/xxsubtype.c - spamdict_type - Modules/xxsubtype.c - spamlist_type - -Modules/_testcapi/monitoring.c - PyCodeLike_Type - +Modules/_testcapi/monitoring.c - PyCodeLike_Type - ##----------------------- ## non-static types - initialized once From e6d7c6a4bc5c74ff6d05036355dfcb6d0c79434e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 18 Mar 2024 17:09:55 +0000 Subject: [PATCH 24/79] skip test if no _testcapi --- Lib/test/test_monitoring.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index abb759b0431271e..5e47a9dd1d3ccf0 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -9,11 +9,12 @@ import types import unittest import asyncio -import _testcapi -from test import support +import test.support from test.support import requires_specialization, script_helper +_testcapi = test.support.import_helper.import_module("_testcapi") + PAIR = (0,1) def f1(): @@ -1883,7 +1884,7 @@ def test_monitoring_live_at_shutdown(self): # gh-115832: An object destructor running during the final GC of # interpreter shutdown triggered an infinite loop in the # instrumentation code. - script = support.findfile("_test_monitoring_shutdown.py") + script = test.support.findfile("_test_monitoring_shutdown.py") script_helper.run_test_script(script) @@ -1892,7 +1893,9 @@ class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): def setUp(self): super(TestCApiEventGeneration, self).setUp() - self.codelike = _testcapi.CodeLike(2) + capi = _testcapi + + self.codelike = capi.CodeLike(2) def cb(name, args): self.results.append((name,) + args) @@ -1902,7 +1905,6 @@ def cb(name, args): self.cb3 = lambda codelike, *args : cb('cb3', args) events = sys.monitoring.events - capi = _testcapi self.cases = [ # (Event, function, *args) (events.PY_START, capi.fire_event_py_start), @@ -1983,7 +1985,7 @@ def test_enter_scope(self): events = sys.monitoring.events capi = _testcapi - cl = _testcapi.CodeLike(2) + cl = capi.CodeLike(2) capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) From 58f2bcff1f20318f2444b230068671404d1dcd5c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 00:34:20 +0000 Subject: [PATCH 25/79] Code review comments --- Lib/test/test_monitoring.py | 172 ++++++++++++++++----------------- Modules/_testcapi/monitoring.c | 85 +++++++--------- Python/instrumentation.c | 3 +- 3 files changed, 120 insertions(+), 140 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 5e47a9dd1d3ccf0..97c9417976b6ec3 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -3,6 +3,7 @@ import collections import dis import functools +import math import operator import sys import textwrap @@ -1904,107 +1905,96 @@ def cb(name, args): self.cb2 = lambda codelike, *args : cb('cb2', args) self.cb3 = lambda codelike, *args : cb('cb3', args) - events = sys.monitoring.events self.cases = [ # (Event, function, *args) - (events.PY_START, capi.fire_event_py_start), - (events.PY_RESUME, capi.fire_event_py_resume), - (events.PY_RETURN, capi.fire_event_py_return, 10), - (events.PY_YIELD, capi.fire_event_py_yield, 20), - (events.CALL, capi.fire_event_call, callable, 30), - (events.LINE, capi.fire_event_line, 40), - (events.JUMP, capi.fire_event_jump, 50), - (events.BRANCH, capi.fire_event_branch, 60), - (events.PY_THROW, capi.fire_event_py_throw, ValueError(1)), - (events.RAISE, capi.fire_event_raise, ValueError(2)), - (events.RERAISE, capi.fire_event_reraise, ValueError(3)), - (events.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), - (events.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), - (events.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), + (1, E.PY_START, capi.fire_event_py_start), + (1, E.PY_RESUME, capi.fire_event_py_resume), + (1, E.PY_RETURN, capi.fire_event_py_return, 10), + (1, E.PY_YIELD, capi.fire_event_py_yield, 20), + (2, E.CALL, capi.fire_event_call, callable, 30), + (3, E.LINE, capi.fire_event_line, 40), + (1, E.JUMP, capi.fire_event_jump, 50), + (1, E.BRANCH, capi.fire_event_branch, 60), + (1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), + (1, E.RAISE, capi.fire_event_raise, ValueError(2)), + (1, E.RERAISE, capi.fire_event_reraise, ValueError(3)), + (1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), + (1, E.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), + (1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), ] + def check_event_count(self, event, func, args, expected): + class Counter: + def __init__(self): + self.count = 0 + def __call__(self, *args): + self.count += 1 + + counter = Counter() + sys.monitoring.register_callback(TEST_TOOL, event, counter) + if event == E.C_RETURN or event == E.C_RAISE: + sys.monitoring.set_events(TEST_TOOL, E.CALL) + else: + sys.monitoring.set_events(TEST_TOOL, event) + event_value = int(math.log2(event)) + _testcapi.enter_scope_single_event(self.codelike, event_value) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + prev = sys.monitoring.register_callback(TEST_TOOL, event, None) + _testcapi.enter_scope_single_event(self.codelike, event_value) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, 0) + self.assertEqual(prev, counter) + sys.monitoring.set_events(TEST_TOOL, 0) + def test_fire_event(self): - for event, function, *args in self.cases: + for expected, event, function, *args in self.cases: offset = 0 - self.codelike = _testcapi.CodeLike(2) - with self.subTest(event): - output = (offset, *args) - # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - sys.monitoring.register_callback(TEST_TOOL, event, self.cb1) - sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) - active = 1 << TEST_TOOL + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__): + args = (self.codelike, 0) + tuple(args) + self.check_event_count(event, function, args, expected) - try: - self.results = [] - # fire one of each event type - for _, function, *args in self.cases: - res = function(self.codelike, offset, active, *args) - self.assertEqual(res, active) + CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, + E.EXCEPTION_HANDLED, E.PY_UNWIND } - self.assertEqual(self.results, [('cb1',) + output]) - finally: - sys.monitoring.register_callback(TEST_TOOL, event, None) - sys.monitoring.register_callback(TEST_TOOL2, event, None) + def check_disable(self, event, func, args, expected): + try: + counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, event, counter) + if event == E.C_RETURN or event == E.C_RAISE: + sys.monitoring.set_events(TEST_TOOL, E.CALL) + else: + sys.monitoring.set_events(TEST_TOOL, event) + event_value = int(math.log2(event)) + _testcapi.enter_scope_single_event(self.codelike, event_value) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + counter.disable = True + if event in self.CANNOT_DISABLE: + with self.assertRaises(ValueError): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + else: + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected - 1) + sys.monitoring.set_events(TEST_TOOL, 0) + finally: + sys.monitoring.restart_events() def test_disable_event(self): - events = sys.monitoring.events - cannot_disable = { events.PY_THROW, events.RAISE, events.RERAISE, - events.EXCEPTION_HANDLED, events.PY_UNWIND } - - def cb_disable(*args): - self.cb1(*args) - return sys.monitoring.DISABLE - - for event, function, *args in self.cases: - offset = 1 + for expected, event, function, *args in self.cases: + offset = 0 self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): - output = (offset, *args) - - sys.monitoring.register_callback(TEST_TOOL, event, cb_disable) - active = 1 << TEST_TOOL - - try: - # fire one of each event type - self.results = [] - for f_event, function, *args in self.cases: - if f_event == event and f_event in cannot_disable: - with self.assertRaises(ValueError): - res = function(self.codelike, offset, active, *args) - self.assertEqual(res, active) - else: - res = function(self.codelike, offset, active, *args) - self.assertEqual(res, 0 if f_event == event else active) - self.assertEqual(self.results, [('cb1',) + output]) - - finally: - sys.monitoring.register_callback(TEST_TOOL, event, None) - sys.monitoring.register_callback(TEST_TOOL2, event, None) - - def test_enter_scope(self): - events = sys.monitoring.events - capi = _testcapi - - cl = capi.CodeLike(2) - capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] - - sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) - - self.results = [] - capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) - capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) - self.assertEqual(self.results, [('cb1', 0)]) - - sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_RETURN, self.cb2) - - self.results = [] - capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) - capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) - self.assertEqual(self.results, [('cb1', 0), ('cb2', 1, 42)]) - - sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, None) + args = (self.codelike, 0) + tuple(args) + self.check_disable(event, function, args, expected) - self.results = [] - capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) - capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) - self.assertEqual(self.results, [('cb2', 1, 42)]) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 1e1527e5838870b..dfb3d3b2d03c522 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -105,6 +105,7 @@ static PyTypeObject PyCodeLike_Type = { .tp_str = (reprfunc) CodeLike_str, }; +#define PyCodeLike_Check(v) Py_IS_TYPE((v), &PyCodeLike_Type) /*******************************************************************/ @@ -112,15 +113,14 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - NULLABLE(codelike); + assert(PyCodeLike_Check(codelike)); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -130,15 +130,14 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } NULLABLE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -148,16 +147,15 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } NULLABLE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); @@ -167,16 +165,15 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } NULLABLE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); @@ -186,9 +183,9 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } NULLABLE(codelike); @@ -196,7 +193,6 @@ fire_event_call(PyObject *self, PyObject *args) PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); RETURN_INT(res == -1 ? -1 : state->active); @@ -206,14 +202,13 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active, lineno; - if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &active, &lineno)) { + int offset, lineno; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); RETURN_INT(res == -1 ? -1 : state->active); @@ -223,15 +218,14 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -241,15 +235,14 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -259,16 +252,15 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -278,16 +270,15 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -297,16 +288,15 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -316,16 +306,15 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -335,16 +324,15 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -354,9 +342,9 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -364,7 +352,6 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -373,16 +360,18 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) /*******************************************************************/ static PyObject * -enter_scope_py_start_py_return(PyObject *self, PyObject *args) +enter_scope_single_event(PyObject *self, PyObject *args) { PyObject *codelike_obj; - if (!PyArg_ParseTuple(args, "O", &codelike_obj)) { + int event; + if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event)) { return NULL; } PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; - uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; - PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 2); + uint8_t events[] = { event }; + + PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 1); Py_RETURN_NONE; } @@ -402,7 +391,7 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope_py_start_py_return", enter_scope_py_start_py_return, METH_VARARGS}, + {"enter_scope_single_event", enter_scope_single_event, METH_VARARGS}, {NULL}, }; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 375fd3f334549f3..60908b1b3fd620b 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2354,7 +2354,8 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, _Py_GlobalMonitors *m = &interp->monitors; for (uint32_t i = 0; i < length; i++) { - state_array[i].active = m->tools[event_types[i]]; + int event = event_types[i]; + state_array[i].active = m->tools[event]; } *version = global_version(interp); } From db5a28693bcfaf8dce378fedf59ec8383f722e3c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 12:36:40 +0000 Subject: [PATCH 26/79] remove unused --- Lib/test/test_monitoring.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 97c9417976b6ec3..d35d415fc1b58be 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1898,13 +1898,6 @@ def setUp(self): self.codelike = capi.CodeLike(2) - def cb(name, args): - self.results.append((name,) + args) - - self.cb1 = lambda codelike, *args : cb('cb1', args) - self.cb2 = lambda codelike, *args : cb('cb2', args) - self.cb3 = lambda codelike, *args : cb('cb3', args) - self.cases = [ # (Event, function, *args) (1, E.PY_START, capi.fire_event_py_start), From 38346e8e6df67ec6932bff4723bd7c8a36b7f224 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 14:46:14 +0000 Subject: [PATCH 27/79] add test with two events --- Lib/test/test_monitoring.py | 42 +++++++++++++++++++++++++++++++--- Modules/_testcapi/monitoring.c | 26 +++++++++++++++------ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index e85582be0f13a77..ca427bc10b456dc 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1933,12 +1933,12 @@ def __call__(self, *args): else: sys.monitoring.set_events(TEST_TOOL, event) event_value = int(math.log2(event)) - _testcapi.enter_scope_single_event(self.codelike, event_value) + _testcapi.enter_scope(self.codelike, event_value) counter.count = 0 func(*args) self.assertEqual(counter.count, expected) prev = sys.monitoring.register_callback(TEST_TOOL, event, None) - _testcapi.enter_scope_single_event(self.codelike, event_value) + _testcapi.enter_scope(self.codelike, event_value) counter.count = 0 func(*args) self.assertEqual(counter.count, 0) @@ -1965,7 +1965,7 @@ def check_disable(self, event, func, args, expected): else: sys.monitoring.set_events(TEST_TOOL, event) event_value = int(math.log2(event)) - _testcapi.enter_scope_single_event(self.codelike, event_value) + _testcapi.enter_scope(self.codelike, event_value) counter.count = 0 func(*args) self.assertEqual(counter.count, expected) @@ -1994,3 +1994,39 @@ def test_disable_event(self): args = (self.codelike, 0) + tuple(args) self.check_disable(event, function, args, expected) + def test_enter_scope_two_events(self): + try: + yield_counter = CounterWithDisable() + unwind_counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) + sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) + + yield_value = int(math.log2(E.PY_YIELD)) + unwind_value = int(math.log2(E.PY_UNWIND)) + cl = _testcapi.CodeLike(2) + _testcapi.enter_scope(cl, yield_value, unwind_value) + + assert(yield_counter.count == 0) + assert(unwind_counter.count == 0) + + _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + sys.monitoring.set_events(TEST_TOOL, 0) + finally: + sys.monitoring.restart_events() diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index dfb3d3b2d03c522..fe7edb6e7345cab 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -360,18 +360,30 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) /*******************************************************************/ static PyObject * -enter_scope_single_event(PyObject *self, PyObject *args) +enter_scope(PyObject *self, PyObject *args) { PyObject *codelike_obj; - int event; - if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event)) { - return NULL; + int event1, event2=0; + int num_events = PyTuple_Size(args) - 1; + if (num_events == 1) { + if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event1)) { + return NULL; + } + } + else { + assert(num_events == 2); + if (!PyArg_ParseTuple(args, "Oii", &codelike_obj, &event1, &event2)) { + return NULL; + } } PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; - uint8_t events[] = { event }; + uint8_t events[] = { event1, event2 }; - PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 1); + PyMonitoring_BeginScope(codelike->monitoring_states, + &codelike->version, + events, + num_events); Py_RETURN_NONE; } @@ -391,7 +403,7 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope_single_event", enter_scope_single_event, METH_VARARGS}, + {"enter_scope", enter_scope, METH_VARARGS}, {NULL}, }; From f5c40fc634e51226e92d43fd880466fc72f3b3f7 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 21:22:54 +0000 Subject: [PATCH 28/79] add _PyMonitoring_EndScope --- Include/cpython/monitoring.h | 3 + Include/monitoring.h | 11 +++ Lib/test/test_monitoring.py | 118 ++++++++++++++++++--------------- Modules/_testcapi/monitoring.c | 7 ++ Python/instrumentation.c | 9 +++ 5 files changed, 95 insertions(+), 53 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 8a42d778aafbff0..cacc338793a45c7 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -6,6 +6,9 @@ PyAPI_FUNC(void) _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); +PyAPI_FUNC(void) +_PyMonitoring_EndScope(void); + PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index 5d1f735ab83b047..4a895c18330a697 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -38,6 +38,17 @@ PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); #endif +#ifndef Py_LIMITED_API +static inline void +PyMonitoring_EndScope(void) +{ + _PyMonitoring_EndScope(); +} +#else +extern void +PyMonitoring_EndScope(void); +#endif + #ifndef Py_LIMITED_API static inline int diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index ca427bc10b456dc..15a04671bff984a 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1894,6 +1894,16 @@ def test_monitoring_live_at_shutdown(self): class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): + class Scope: + def __init__(self, *args): + self.args = args + + def __enter__(self): + _testcapi.enter_scope(*self.args) + + def __exit__(self, *args): + _testcapi.exit_scope() + def setUp(self): super(TestCApiEventGeneration, self).setUp() @@ -1926,24 +1936,27 @@ def __init__(self): def __call__(self, *args): self.count += 1 - counter = Counter() - sys.monitoring.register_callback(TEST_TOOL, event, counter) - if event == E.C_RETURN or event == E.C_RAISE: - sys.monitoring.set_events(TEST_TOOL, E.CALL) - else: - sys.monitoring.set_events(TEST_TOOL, event) - event_value = int(math.log2(event)) - _testcapi.enter_scope(self.codelike, event_value) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) - prev = sys.monitoring.register_callback(TEST_TOOL, event, None) - _testcapi.enter_scope(self.codelike, event_value) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, 0) - self.assertEqual(prev, counter) - sys.monitoring.set_events(TEST_TOOL, 0) + try: + counter = Counter() + sys.monitoring.register_callback(TEST_TOOL, event, counter) + if event == E.C_RETURN or event == E.C_RAISE: + sys.monitoring.set_events(TEST_TOOL, E.CALL) + else: + sys.monitoring.set_events(TEST_TOOL, event) + event_value = int(math.log2(event)) + with self.Scope(self.codelike, event_value): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + + prev = sys.monitoring.register_callback(TEST_TOOL, event, None) + with self.Scope(self.codelike, event_value): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, 0) + self.assertEqual(prev, counter) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) def test_fire_event(self): for expected, event, function, *args in self.cases: @@ -1965,23 +1978,23 @@ def check_disable(self, event, func, args, expected): else: sys.monitoring.set_events(TEST_TOOL, event) event_value = int(math.log2(event)) - _testcapi.enter_scope(self.codelike, event_value) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) - counter.disable = True - if event in self.CANNOT_DISABLE: - with self.assertRaises(ValueError): - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) - else: + with self.Scope(self.codelike, event_value): counter.count = 0 func(*args) self.assertEqual(counter.count, expected) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected - 1) + counter.disable = True + if event in self.CANNOT_DISABLE: + with self.assertRaises(ValueError): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + else: + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected - 1) sys.monitoring.set_events(TEST_TOOL, 0) finally: sys.monitoring.restart_events() @@ -2005,27 +2018,26 @@ def test_enter_scope_two_events(self): yield_value = int(math.log2(E.PY_YIELD)) unwind_value = int(math.log2(E.PY_UNWIND)) cl = _testcapi.CodeLike(2) - _testcapi.enter_scope(cl, yield_value, unwind_value) - - assert(yield_counter.count == 0) - assert(unwind_counter.count == 0) - - _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) - assert(yield_counter.count == 0) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 1) - assert(unwind_counter.count == 1) - - yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) + with self.Scope(cl, yield_value, unwind_value): + yield_counter.count = 0 + unwind_counter.count = 0 + + _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) sys.monitoring.set_events(TEST_TOOL, 0) finally: diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index fe7edb6e7345cab..bd913c0323bc45c 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -388,6 +388,12 @@ enter_scope(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +exit_scope(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + static PyMethodDef TestMethods[] = { {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, @@ -404,6 +410,7 @@ static PyMethodDef TestMethods[] = { {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, {"enter_scope", enter_scope, METH_VARARGS}, + {"exit_scope", exit_scope, METH_VARARGS}, {NULL}, }; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 60908b1b3fd620b..c83218b6ed48c61 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2360,6 +2360,11 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, *version = global_version(interp); } +void +_PyMonitoring_EndScope(void) +{ +} + int _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -2517,6 +2522,10 @@ PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, _PyMonitoring_BeginScope(state_array, version, event_types, length); } +void +PyMonitoring_EndScope() +{ +} int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) From 95c5275304a41c16e88f935b5f7e76e5c8c01eba Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 22:22:21 +0000 Subject: [PATCH 29/79] Begin/End --> Enter/Exit --- Include/cpython/monitoring.h | 4 ++-- Include/monitoring.h | 12 ++++++------ Modules/_testcapi/monitoring.c | 3 ++- Python/instrumentation.c | 10 +++++----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index cacc338793a45c7..c2ce3fd6a25fee4 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -3,11 +3,11 @@ #endif PyAPI_FUNC(void) -_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) -_PyMonitoring_EndScope(void); +_PyMonitoring_ExitScope(void); PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index 4a895c18330a697..9ba4c2b3ac0a6f8 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -27,26 +27,26 @@ typedef struct _PyMonitoringState { #ifndef Py_LIMITED_API static inline void -PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { - _PyMonitoring_BeginScope(state_array, version, event_types, length); + _PyMonitoring_EnterScope(state_array, version, event_types, length); } #else extern void -PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); #endif #ifndef Py_LIMITED_API static inline void -PyMonitoring_EndScope(void) +PyMonitoring_ExitScope(void) { - _PyMonitoring_EndScope(); + _PyMonitoring_ExitScope(); } #else extern void -PyMonitoring_EndScope(void); +PyMonitoring_ExitScope(void); #endif diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index bd913c0323bc45c..9737f5e2f60176d 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -380,7 +380,7 @@ enter_scope(PyObject *self, PyObject *args) uint8_t events[] = { event1, event2 }; - PyMonitoring_BeginScope(codelike->monitoring_states, + PyMonitoring_EnterScope(codelike->monitoring_states, &codelike->version, events, num_events); @@ -391,6 +391,7 @@ enter_scope(PyObject *self, PyObject *args) static PyObject * exit_scope(PyObject *self, PyObject *args) { + PyMonitoring_ExitScope(); Py_RETURN_NONE; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index c83218b6ed48c61..8f8352113e0505a 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2344,7 +2344,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs } void -_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); @@ -2361,7 +2361,7 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, } void -_PyMonitoring_EndScope(void) +_PyMonitoring_ExitScope(void) { } @@ -2516,14 +2516,14 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik #ifdef Py_LIMITED_API void -PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) { - _PyMonitoring_BeginScope(state_array, version, event_types, length); + _PyMonitoring_EnterScope(state_array, version, event_types, length); } void -PyMonitoring_EndScope() +PyMonitoring_ExitScope() { } From 427e1162c8e388e9b24c890415b00f13ad1cd4fa Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 22:58:28 +0000 Subject: [PATCH 30/79] error checking --- Modules/_testcapi/monitoring.c | 38 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 9737f5e2f60176d..a7146f4236e506c 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -105,7 +105,10 @@ static PyTypeObject PyCodeLike_Type = { .tp_str = (reprfunc) CodeLike_str, }; -#define PyCodeLike_Check(v) Py_IS_TYPE((v), &PyCodeLike_Type) +#define RAISE_UNLESS_CODELIKE(v) if (!Py_IS_TYPE((v), &PyCodeLike_Type)) { \ + PyErr_Format(PyExc_TypeError, "expected a code-like, got %s", Py_TYPE(v)->tp_name); \ + return NULL; \ + } /*******************************************************************/ @@ -117,7 +120,7 @@ fire_event_py_start(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - assert(PyCodeLike_Check(codelike)); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -134,7 +137,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - NULLABLE(codelike); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -152,7 +155,7 @@ fire_event_py_return(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - NULLABLE(codelike); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -170,7 +173,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - NULLABLE(codelike); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -188,8 +191,8 @@ fire_event_call(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } - NULLABLE(codelike); NULLABLE(arg0); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -206,6 +209,7 @@ fire_event_line(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -223,6 +227,7 @@ fire_event_jump(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -240,6 +245,7 @@ fire_event_branch(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -258,6 +264,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -276,6 +283,7 @@ fire_event_raise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -294,6 +302,7 @@ fire_event_reraise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -312,6 +321,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -330,6 +340,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -348,7 +359,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -362,26 +373,27 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) static PyObject * enter_scope(PyObject *self, PyObject *args) { - PyObject *codelike_obj; + PyObject *codelike; int event1, event2=0; int num_events = PyTuple_Size(args) - 1; if (num_events == 1) { - if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event1)) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { return NULL; } } else { assert(num_events == 2); - if (!PyArg_ParseTuple(args, "Oii", &codelike_obj, &event1, &event2)) { + if (!PyArg_ParseTuple(args, "Oii", &codelike, &event1, &event2)) { return NULL; } } - PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = (PyCodeLikeObject *) codelike; uint8_t events[] = { event1, event2 }; - PyMonitoring_EnterScope(codelike->monitoring_states, - &codelike->version, + PyMonitoring_EnterScope(cl->monitoring_states, + &cl->version, events, num_events); From 3bc47df115f02d3d6242a2bf5426da638c2908a8 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 23:15:05 +0000 Subject: [PATCH 31/79] review comments --- Modules/_testcapi/monitoring.c | 2 +- Python/instrumentation.c | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index a7146f4236e506c..7ece3987972cc67 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -375,7 +375,7 @@ enter_scope(PyObject *self, PyObject *args) { PyObject *codelike; int event1, event2=0; - int num_events = PyTuple_Size(args) - 1; + Py_ssize_t num_events = PyTuple_Size(args) - 1; if (num_events == 1) { if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { return NULL; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 8f8352113e0505a..0d4efc5c5baefed 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2511,9 +2511,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik PY_MONITORING_EVENT_STOP_ITERATION); } - - -#ifdef Py_LIMITED_API +/******************* Public API *******************/ void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, @@ -2649,5 +2647,3 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike { IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } - -#endif From 5f11cdaabcb968449fab4c139a04d6bf24a0c188 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 23:20:45 +0000 Subject: [PATCH 32/79] uint32_t --> int --- Python/instrumentation.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 0d4efc5c5baefed..efcb6b5ec84b5a5 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2526,123 +2526,123 @@ PyMonitoring_ExitScope() } int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); } int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno); { IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); } int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); } int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); { IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); From e719e38fcf4f825b6aa1b848956a61f6d2e2217b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 23:21:19 +0000 Subject: [PATCH 33/79] put ifdef back --- Python/instrumentation.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index efcb6b5ec84b5a5..777ee1e6d711a24 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2513,6 +2513,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik /******************* Public API *******************/ +#ifdef Py_LIMITED_API void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) @@ -2647,3 +2648,5 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike { IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } + +#endif From be236b170b3d717ec24c73862136e570315cf234 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 20 Mar 2024 15:57:58 +0000 Subject: [PATCH 34/79] add opaque --- Include/monitoring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/monitoring.h b/Include/monitoring.h index 9ba4c2b3ac0a6f8..ce50b844775c4f5 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -7,6 +7,7 @@ extern "C" { typedef struct _PyMonitoringState { uint8_t active; + uint8_t opaque; } PyMonitoringState; From 8c1eacf5bee27404f7b721dba1da0e758929fb3a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 20 Mar 2024 23:47:42 +0000 Subject: [PATCH 35/79] always define the private versions. PyUnstable_ for the inlined --- Include/cpython/monitoring.h | 85 ++++++++++++++++- Include/monitoring.h | 170 +++++++++++++++------------------ Lib/test/test_monitoring.py | 35 ++++--- Modules/_testcapi/monitoring.c | 57 +++++++++++ Python/instrumentation.c | 106 ++++++++++++-------- 5 files changed, 302 insertions(+), 151 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index c2ce3fd6a25fee4..3c536a26efd8f86 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -3,82 +3,161 @@ #endif PyAPI_FUNC(void) +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, + const uint8_t *event_types, uint32_t length); + +void _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) +PyMonitoring_ExitScope(void); + +void _PyMonitoring_ExitScope(void); PyAPI_FUNC(int) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +int _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +int _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +int _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +int _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0); + +int _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0); + +int _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno); + +int _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); PyAPI_FUNC(int) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +int _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +int _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +int _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); + PyObject *retval); PyAPI_FUNC(int) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); + PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); +int +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index ce50b844775c4f5..f6348a268c2d15d 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -2,7 +2,6 @@ #define Py_MONITORING_H #ifdef __cplusplus extern "C" { - #endif typedef struct _PyMonitoringState { @@ -11,7 +10,6 @@ typedef struct _PyMonitoringState { } PyMonitoringState; -#ifndef Py_LIMITED_API # define Py_CPYTHON_MONITORING_H # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H @@ -24,301 +22,283 @@ typedef struct _PyMonitoringState { return 0; \ } -#endif #ifndef Py_LIMITED_API static inline void -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) +PyUnstable_Monitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, + const uint8_t *event_types, uint32_t length) { _PyMonitoring_EnterScope(state_array, version, event_types, length); } -#else +#endif + extern void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); -#endif #ifndef Py_LIMITED_API static inline void -PyMonitoring_ExitScope(void) +PyUnstable_Monitoring_ExitScope(void) { _PyMonitoring_ExitScope(); } -#else +#endif + extern void PyMonitoring_ExitScope(void); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } -#else +#endif + extern int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } -#else +#endif + extern int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } -#else +#endif + extern int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } -#else +#endif + extern int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) +PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( state, - _PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } -#else -extern int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); #endif -#ifndef Py_LIMITED_API -static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - _PyMonitoring_IF_ACTIVE( - state, - _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); -} -#else extern int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) +PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } -#else +#endif + extern int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } -#else +#endif + extern int PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } -#else +#endif + extern int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } -#else +#endif + extern int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) +PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PyMonitoring_IF_ACTIVE( state, - _PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } -#else +#endif + extern int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); -#endif + PyObject *retval); #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) +PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, - _PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); -#endif + PyObject *exception); #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif -#ifndef Py_LIMITED_API #undef _PyMonitoring_IF_ACTIVE -#endif #ifdef __cplusplus } diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 15a04671bff984a..efdeb717a23e279 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1913,20 +1913,19 @@ def setUp(self): self.cases = [ # (Event, function, *args) - (1, E.PY_START, capi.fire_event_py_start), - (1, E.PY_RESUME, capi.fire_event_py_resume), - (1, E.PY_RETURN, capi.fire_event_py_return, 10), - (1, E.PY_YIELD, capi.fire_event_py_yield, 20), - (2, E.CALL, capi.fire_event_call, callable, 30), - (3, E.LINE, capi.fire_event_line, 40), - (1, E.JUMP, capi.fire_event_jump, 50), - (1, E.BRANCH, capi.fire_event_branch, 60), - (1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), - (1, E.RAISE, capi.fire_event_raise, ValueError(2)), - (1, E.RERAISE, capi.fire_event_reraise, ValueError(3)), - (1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), - (1, E.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), - (1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), + ( 1, E.PY_START, capi.fire_event_py_start), + ( 1, E.PY_RESUME, capi.fire_event_py_resume), + ( 1, E.PY_YIELD, capi.fire_event_py_yield, 10), + ( 1, E.PY_RETURN, capi.fire_event_py_return, 20), + ( 2, E.CALL, capi.fire_event_call, callable, 40), + (10, E.INSTRUCTION, capi.fire_event_instruction), + ( 1, E.JUMP, capi.fire_event_jump, 60), + ( 1, E.BRANCH, capi.fire_event_branch, 70), + ( 1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), + ( 1, E.RAISE, capi.fire_event_raise, ValueError(2)), + ( 1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(5)), + ( 1, E.PY_UNWIND, capi.fire_event_py_unwind, ValueError(6)), + ( 1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(7)), ] def check_event_count(self, event, func, args, expected): @@ -1984,10 +1983,16 @@ def check_disable(self, event, func, args, expected): self.assertEqual(counter.count, expected) counter.disable = True if event in self.CANNOT_DISABLE: - with self.assertRaises(ValueError): + # use try-except rather then assertRaises to avoid + # events from framework code + try: counter.count = 0 func(*args) self.assertEqual(counter.count, expected) + except ValueError: + pass + else: + self.Error("Expected a ValueError") else: counter.count = 0 func(*args) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 7ece3987972cc67..e3c8ead8f68d2f8 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -164,6 +164,24 @@ fire_event_py_return(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } +static PyObject * +fire_event_c_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { @@ -218,6 +236,23 @@ fire_event_line(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } +static PyObject * +fire_event_instruction(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + static PyObject * fire_event_jump(PyObject *self, PyObject *args) { @@ -292,6 +327,25 @@ fire_event_raise(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } +static PyObject * +fire_event_c_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { @@ -411,13 +465,16 @@ static PyMethodDef TestMethods[] = { {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, + {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, {"fire_event_call", fire_event_call, METH_VARARGS}, + {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, {"fire_event_branch", fire_event_branch, METH_VARARGS}, {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, {"fire_event_raise", fire_event_raise, METH_VARARGS}, + {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 777ee1e6d711a24..40802a571af172a 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2431,6 +2431,16 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int of return res; } +int +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) +{ + assert(state->active); + PyObject *args[3] = { NULL, NULL, NULL }; + int res= capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_INSTRUCTION); + return res; +} + int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) @@ -2451,6 +2461,16 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int PY_MONITORING_EVENT_BRANCH); } +int +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + assert(state->active); + PyObject *args[4] = { NULL, NULL, NULL, retval }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_C_RETURN); +} + int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -2471,6 +2491,16 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int o PY_MONITORING_EVENT_RAISE); } +int +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + assert(state->active); + PyObject *args[4] = { NULL, NULL, NULL, exception }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_C_RAISE); +} + int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -2513,140 +2543,140 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik /******************* Public API *******************/ -#ifdef Py_LIMITED_API void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + const uint8_t *event_types, uint32_t length) { _PyMonitoring_EnterScope(state_array, version, event_types, length); } void -PyMonitoring_ExitScope() +PyMonitoring_ExitScope(void) { } +#define IF_ACTIVE(STATE, X) \ + if ((STATE)->active) { \ + return (X); \ + } \ + else { \ + return 0; \ + } + int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); + IF_ACTIVE(state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); + IF_ACTIVE(state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); + IF_ACTIVE(state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno); + int lineno) { - IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); + IF_ACTIVE(state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } int PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); -} - -int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); + IF_ACTIVE(state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); + IF_ACTIVE(state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + IF_ACTIVE(state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) + PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); + PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + IF_ACTIVE(state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) + PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#endif +#undef IF_ACTIVE From 23f579ba1d5e73050b073dd6e781c2a61ce21d65 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 21 Mar 2024 13:42:40 +0000 Subject: [PATCH 36/79] add tests for the Unstable version of the API --- Include/cpython/monitoring.h | 42 +++---- Lib/test/test_monitoring.py | 92 +++++++-------- Modules/_testcapi/monitoring.c | 204 ++++++++++++++++++++++++--------- 3 files changed, 221 insertions(+), 117 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 3c536a26efd8f86..87f3d35d3d98942 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -6,33 +6,33 @@ PyAPI_FUNC(void) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); -void +PyAPI_FUNC(void) _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) PyMonitoring_ExitScope(void); -void +PyAPI_FUNC(void) _PyMonitoring_ExitScope(void); PyAPI_FUNC(int) PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); @@ -40,7 +40,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); @@ -48,7 +48,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); @@ -56,7 +56,7 @@ PyAPI_FUNC(int) PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); @@ -64,21 +64,21 @@ PyAPI_FUNC(int) PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -int +PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); PyAPI_FUNC(int) PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); @@ -86,7 +86,7 @@ PyAPI_FUNC(int) PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); @@ -94,7 +94,7 @@ PyAPI_FUNC(int) PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); @@ -102,7 +102,7 @@ PyAPI_FUNC(int) PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); @@ -110,7 +110,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -118,7 +118,7 @@ PyAPI_FUNC(int) PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -126,7 +126,7 @@ PyAPI_FUNC(int) PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -134,7 +134,7 @@ PyAPI_FUNC(int) PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -142,7 +142,7 @@ PyAPI_FUNC(int) PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -150,7 +150,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -158,6 +158,6 @@ PyAPI_FUNC(int) PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index efdeb717a23e279..d8a6286030c5def 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1959,11 +1959,12 @@ def __call__(self, *args): def test_fire_event(self): for expected, event, function, *args in self.cases: - offset = 0 - self.codelike = _testcapi.CodeLike(1) - with self.subTest(function.__name__): - args = (self.codelike, 0) + tuple(args) - self.check_event_count(event, function, args, expected) + for unstable in (0, 1): + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__, unstable=unstable): + args_ = (self.codelike, 0, unstable) + tuple(args) + self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, E.EXCEPTION_HANDLED, E.PY_UNWIND } @@ -2000,50 +2001,51 @@ def check_disable(self, event, func, args, expected): counter.count = 0 func(*args) self.assertEqual(counter.count, expected - 1) - sys.monitoring.set_events(TEST_TOOL, 0) finally: - sys.monitoring.restart_events() + sys.monitoring.set_events(TEST_TOOL, 0) def test_disable_event(self): for expected, event, function, *args in self.cases: - offset = 0 - self.codelike = _testcapi.CodeLike(2) - with self.subTest(function.__name__): - args = (self.codelike, 0) + tuple(args) - self.check_disable(event, function, args, expected) + for unstable in (0, 1): + offset = 0 + self.codelike = _testcapi.CodeLike(2) + with self.subTest(function.__name__, unstable=unstable): + args_ = (self.codelike, 0, unstable) + tuple(args) + self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): - try: - yield_counter = CounterWithDisable() - unwind_counter = CounterWithDisable() - sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) - sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) - sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) - - yield_value = int(math.log2(E.PY_YIELD)) - unwind_value = int(math.log2(E.PY_UNWIND)) - cl = _testcapi.CodeLike(2) - with self.Scope(cl, yield_value, unwind_value): - yield_counter.count = 0 - unwind_counter.count = 0 - - _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) - assert(yield_counter.count == 0) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 1) - assert(unwind_counter.count == 1) - - yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) + for unstable in (0,1): + with self.subTest(unstable=unstable): + try: + yield_counter = CounterWithDisable() + unwind_counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) + sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) + + yield_value = int(math.log2(E.PY_YIELD)) + unwind_value = int(math.log2(E.PY_UNWIND)) + cl = _testcapi.CodeLike(2) + with self.Scope(cl, yield_value, unwind_value): + yield_counter.count = 0 + unwind_counter.count = 0 + + _testcapi.fire_event_py_unwind(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) - sys.monitoring.set_events(TEST_TOOL, 0) - finally: - sys.monitoring.restart_events() + finally: + sys.monitoring.set_events(TEST_TOOL, 0) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index e3c8ead8f68d2f8..877cdb7245f8027 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -116,8 +116,8 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + int offset, unstable; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -125,7 +125,13 @@ fire_event_py_start(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyStartEvent(state, codelike, offset); + } + else { + res = PyMonitoring_FirePyStartEvent(state, codelike, offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -133,8 +139,8 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + int offset, unstable; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -142,7 +148,13 @@ fire_event_py_resume(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyResumeEvent(state, codelike, offset); + } + else { + res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -150,9 +162,9 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -160,7 +172,13 @@ fire_event_py_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyReturnEvent(state, codelike, offset, retval); + } + else { + res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -168,9 +186,9 @@ static PyObject * fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -178,7 +196,13 @@ fire_event_c_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireCReturnEvent(state, codelike, offset, retval); + } + else { + res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -186,9 +210,9 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -196,7 +220,13 @@ fire_event_py_yield(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyYieldEvent(state, codelike, offset, retval); + } + else { + res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -204,9 +234,9 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &unstable, &callable, &arg0)) { return NULL; } NULLABLE(arg0); @@ -215,7 +245,13 @@ fire_event_call(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireCallEvent(state, codelike, offset, callable, arg0); + } + else { + res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -223,8 +259,8 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, lineno; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { + int offset, unstable, lineno; + if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &unstable, &lineno)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -232,7 +268,13 @@ fire_event_line(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireLineEvent(state, codelike, offset, lineno); + } + else { + res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -240,8 +282,8 @@ static PyObject * fire_event_instruction(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + int offset, unstable; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -249,7 +291,13 @@ fire_event_instruction(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireInstructionEvent(state, codelike, offset); + } + else { + res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -257,9 +305,9 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -267,7 +315,13 @@ fire_event_jump(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireJumpEvent(state, codelike, offset, target_offset); + } + else { + res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -275,9 +329,9 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -285,7 +339,13 @@ fire_event_branch(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireBranchEvent(state, codelike, offset, target_offset); + } + else { + res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -293,9 +353,9 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -304,7 +364,13 @@ fire_event_py_throw(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyThrowEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -312,9 +378,9 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -323,7 +389,13 @@ fire_event_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireRaiseEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -331,9 +403,9 @@ static PyObject * fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -342,7 +414,13 @@ fire_event_c_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireCRaiseEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -350,9 +428,9 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -361,7 +439,13 @@ fire_event_reraise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireReraiseEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -369,9 +453,9 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -380,7 +464,13 @@ fire_event_exception_handled(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -388,9 +478,9 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -399,7 +489,13 @@ fire_event_py_unwind(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyUnwindEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -407,9 +503,9 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -418,7 +514,13 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireStopIterationEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } From eee637e97a611d935563d978616fd4c53e103a91 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 21 Mar 2024 14:10:21 +0000 Subject: [PATCH 37/79] tidy up declarations --- Include/cpython/monitoring.h | 80 --------------- Include/monitoring.h | 187 ++++++++++++++--------------------- 2 files changed, 75 insertions(+), 192 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 87f3d35d3d98942..deb64561a8332f5 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,162 +2,82 @@ # error "this header file must not be included directly" #endif -PyAPI_FUNC(void) -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); - PyAPI_FUNC(void) _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); -PyAPI_FUNC(void) -PyMonitoring_ExitScope(void); - PyAPI_FUNC(void) _PyMonitoring_ExitScope(void); -PyAPI_FUNC(int) -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); - PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); -PyAPI_FUNC(int) -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); - PyAPI_FUNC(int) _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); -PyAPI_FUNC(int) -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - PyAPI_FUNC(int) _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - PyAPI_FUNC(int) _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -PyAPI_FUNC(int) -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -PyAPI_FUNC(int) -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno); - PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -PyAPI_FUNC(int) -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); - PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -PyAPI_FUNC(int) -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -PyAPI_FUNC(int) -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -PyAPI_FUNC(int) -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -PyAPI_FUNC(int) -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index f6348a268c2d15d..d71e02d3817f488 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -14,6 +14,79 @@ typedef struct _PyMonitoringState { # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H +PyAPI_FUNC(void) +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, + const uint8_t *event_types, uint32_t length); + +PyAPI_FUNC(void) +PyMonitoring_ExitScope(void); + +PyAPI_FUNC(int) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +PyAPI_FUNC(int) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +PyAPI_FUNC(int) +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +PyAPI_FUNC(int) +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +PyAPI_FUNC(int) +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0); + +PyAPI_FUNC(int) +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno); + +PyAPI_FUNC(int) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +PyAPI_FUNC(int) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +PyAPI_FUNC(int) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); +PyAPI_FUNC(int) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +#ifndef Py_LIMITED_API + #define _PyMonitoring_IF_ACTIVE(STATE, X) \ if ((STATE)->active) { \ return (X); \ @@ -23,32 +96,19 @@ typedef struct _PyMonitoringState { } -#ifndef Py_LIMITED_API static inline void PyUnstable_Monitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { _PyMonitoring_EnterScope(state_array, version, event_types, length); } -#endif -extern void -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); - -#ifndef Py_LIMITED_API static inline void PyUnstable_Monitoring_ExitScope(void) { _PyMonitoring_ExitScope(); } -#endif -extern void -PyMonitoring_ExitScope(void); - - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -56,13 +116,7 @@ PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } -#endif -extern int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); - - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -70,12 +124,7 @@ PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *code state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } -#endif -extern int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) @@ -84,13 +133,7 @@ PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *code state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } -#endif -extern int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) @@ -99,13 +142,7 @@ PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } -#endif -extern int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) @@ -114,13 +151,7 @@ PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } -#endif -extern int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno) @@ -129,13 +160,7 @@ PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } -#endif -extern int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -143,12 +168,7 @@ PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *c state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } -#endif - -extern int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) @@ -157,13 +177,7 @@ PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } -#endif -extern int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) @@ -172,13 +186,7 @@ PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codeli state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } -#endif -extern int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) @@ -187,13 +195,7 @@ PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } -#endif - -extern int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -202,13 +204,7 @@ PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -217,13 +213,7 @@ PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelik state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -232,13 +222,7 @@ PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -247,13 +231,7 @@ PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObje state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } -#endif -extern int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -262,13 +240,7 @@ PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codeli state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } -#endif -extern int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -277,13 +249,7 @@ PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *code state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -292,13 +258,10 @@ PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); #undef _PyMonitoring_IF_ACTIVE +#endif + #ifdef __cplusplus } From 29c01e37e1183af1de17af6c19cfa090baad732d Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 21 Mar 2024 16:31:11 +0000 Subject: [PATCH 38/79] private versions are not in limited API --- Include/cpython/monitoring.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index deb64561a8332f5..362fdf5e99ef80a 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,6 +2,8 @@ # error "this header file must not be included directly" #endif +#ifndef Py_LIMITED_API + PyAPI_FUNC(void) _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); @@ -81,3 +83,5 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, in PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); + +#endif From ef9a4a1f179c264521ac235e6af45d68cc808141 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 25 Mar 2024 16:18:04 +0000 Subject: [PATCH 39/79] rename macro --- Include/monitoring.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Include/monitoring.h b/Include/monitoring.h index d71e02d3817f488..3e56f594790cb74 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -87,7 +87,7 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike #ifndef Py_LIMITED_API -#define _PyMonitoring_IF_ACTIVE(STATE, X) \ +#define _PYMONITORING_IF_ACTIVE(STATE, X) \ if ((STATE)->active) { \ return (X); \ } \ @@ -112,7 +112,7 @@ PyUnstable_Monitoring_ExitScope(void) static inline int PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } @@ -120,7 +120,7 @@ PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codel static inline int PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } @@ -129,7 +129,7 @@ static inline int PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } @@ -138,7 +138,7 @@ static inline int PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } @@ -147,7 +147,7 @@ static inline int PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } @@ -156,7 +156,7 @@ static inline int PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } @@ -164,7 +164,7 @@ PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike static inline int PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } @@ -173,7 +173,7 @@ static inline int PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } @@ -182,7 +182,7 @@ static inline int PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } @@ -191,7 +191,7 @@ static inline int PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } @@ -200,7 +200,7 @@ static inline int PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } @@ -209,7 +209,7 @@ static inline int PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } @@ -218,7 +218,7 @@ static inline int PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } @@ -227,7 +227,7 @@ static inline int PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } @@ -236,7 +236,7 @@ static inline int PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } @@ -245,7 +245,7 @@ static inline int PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } @@ -254,12 +254,12 @@ static inline int PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#undef _PyMonitoring_IF_ACTIVE +#undef _PYMONITORING_IF_ACTIVE #endif From c0bcc2205e8038af91821bdbefcaf9c3090deabd Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 26 Mar 2024 19:39:35 +0000 Subject: [PATCH 40/79] update limited API --- Doc/data/stable_abi.dat | 19 ++++++++++++++ Lib/test/test_stable_abi_ctypes.py | 19 ++++++++++++++ Misc/stable_abi.toml | 40 ++++++++++++++++++++++++++++++ PC/python3dll.c | 19 ++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 2763bea5137cc72..0132d3527aa8361 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -433,6 +433,25 @@ function,PyModule_New,3.2,, function,PyModule_NewObject,3.7,, function,PyModule_SetDocString,3.7,, var,PyModule_Type,3.2,, +function,PyMonitoring_EnterScope,3.13,, +function,PyMonitoring_ExitScope,3.13,, +function,PyMonitoring_FireBranchEvent,3.13,, +function,PyMonitoring_FireCRaiseEvent,3.13,, +function,PyMonitoring_FireCReturnEvent,3.13,, +function,PyMonitoring_FireCallEvent,3.13,, +function,PyMonitoring_FireExceptionHandledEvent,3.13,, +function,PyMonitoring_FireInstructionEvent,3.13,, +function,PyMonitoring_FireJumpEvent,3.13,, +function,PyMonitoring_FireLineEvent,3.13,, +function,PyMonitoring_FirePyResumeEvent,3.13,, +function,PyMonitoring_FirePyReturnEvent,3.13,, +function,PyMonitoring_FirePyStartEvent,3.13,, +function,PyMonitoring_FirePyThrowEvent,3.13,, +function,PyMonitoring_FirePyUnwindEvent,3.13,, +function,PyMonitoring_FirePyYieldEvent,3.13,, +function,PyMonitoring_FireRaiseEvent,3.13,, +function,PyMonitoring_FireReraiseEvent,3.13,, +function,PyMonitoring_FireStopIterationEvent,3.13,, function,PyNumber_Absolute,3.2,, function,PyNumber_Add,3.2,, function,PyNumber_And,3.2,, diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index d0e4f3c71c15e07..55f2646dffc046f 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -464,6 +464,25 @@ def test_windows_feature_macros(self): "PyModule_NewObject", "PyModule_SetDocString", "PyModule_Type", + "PyMonitoring_EnterScope", + "PyMonitoring_ExitScope", + "PyMonitoring_FireBranchEvent", + "PyMonitoring_FireCRaiseEvent", + "PyMonitoring_FireCReturnEvent", + "PyMonitoring_FireCallEvent", + "PyMonitoring_FireExceptionHandledEvent", + "PyMonitoring_FireInstructionEvent", + "PyMonitoring_FireJumpEvent", + "PyMonitoring_FireLineEvent", + "PyMonitoring_FirePyResumeEvent", + "PyMonitoring_FirePyReturnEvent", + "PyMonitoring_FirePyStartEvent", + "PyMonitoring_FirePyThrowEvent", + "PyMonitoring_FirePyUnwindEvent", + "PyMonitoring_FirePyYieldEvent", + "PyMonitoring_FireRaiseEvent", + "PyMonitoring_FireReraiseEvent", + "PyMonitoring_FireStopIterationEvent", "PyNumber_Absolute", "PyNumber_Add", "PyNumber_And", diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 14dda7db1c323e2..2ceea2b81cdeaea 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2506,3 +2506,43 @@ added = '3.13' [function.PyType_GetModuleByDef] added = '3.13' + +# Add API for Monitoring in Python 3.13 (https://github.com/python/cpython/issues/111997) +[function.PyMonitoring_EnterScope] + added = '3.13' +[function.PyMonitoring_ExitScope] + added = '3.13' +[function.PyMonitoring_FireBranchEvent] + added = '3.13' +[function.PyMonitoring_FireCRaiseEvent] + added = '3.13' +[function.PyMonitoring_FireCReturnEvent] + added = '3.13' +[function.PyMonitoring_FireCallEvent] + added = '3.13' +[function.PyMonitoring_FireExceptionHandledEvent] + added = '3.13' +[function.PyMonitoring_FireInstructionEvent] + added = '3.13' +[function.PyMonitoring_FireJumpEvent] + added = '3.13' +[function.PyMonitoring_FireLineEvent] + added = '3.13' +[function.PyMonitoring_FirePyResumeEvent] + added = '3.13' +[function.PyMonitoring_FirePyReturnEvent] + added = '3.13' +[function.PyMonitoring_FirePyStartEvent] + added = '3.13' +[function.PyMonitoring_FirePyThrowEvent] + added = '3.13' +[function.PyMonitoring_FirePyUnwindEvent] + added = '3.13' +[function.PyMonitoring_FirePyYieldEvent] + added = '3.13' +[function.PyMonitoring_FireRaiseEvent] + added = '3.13' +[function.PyMonitoring_FireReraiseEvent] + added = '3.13' +[function.PyMonitoring_FireStopIterationEvent] + added = '3.13' diff --git a/PC/python3dll.c b/PC/python3dll.c index c6fdc0bd73b9fe7..8223e98be206f68 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -409,6 +409,25 @@ EXPORT_FUNC(PyModule_New) EXPORT_FUNC(PyModule_NewObject) EXPORT_FUNC(PyModule_SetDocString) EXPORT_FUNC(PyModuleDef_Init) +EXPORT_FUNC(PyMonitoring_EnterScope) +EXPORT_FUNC(PyMonitoring_ExitScope) +EXPORT_FUNC(PyMonitoring_FireBranchEvent) +EXPORT_FUNC(PyMonitoring_FireCallEvent) +EXPORT_FUNC(PyMonitoring_FireCRaiseEvent) +EXPORT_FUNC(PyMonitoring_FireCReturnEvent) +EXPORT_FUNC(PyMonitoring_FireExceptionHandledEvent) +EXPORT_FUNC(PyMonitoring_FireInstructionEvent) +EXPORT_FUNC(PyMonitoring_FireJumpEvent) +EXPORT_FUNC(PyMonitoring_FireLineEvent) +EXPORT_FUNC(PyMonitoring_FirePyResumeEvent) +EXPORT_FUNC(PyMonitoring_FirePyReturnEvent) +EXPORT_FUNC(PyMonitoring_FirePyStartEvent) +EXPORT_FUNC(PyMonitoring_FirePyThrowEvent) +EXPORT_FUNC(PyMonitoring_FirePyUnwindEvent) +EXPORT_FUNC(PyMonitoring_FirePyYieldEvent) +EXPORT_FUNC(PyMonitoring_FireRaiseEvent) +EXPORT_FUNC(PyMonitoring_FireReraiseEvent) +EXPORT_FUNC(PyMonitoring_FireStopIterationEvent) EXPORT_FUNC(PyNumber_Absolute) EXPORT_FUNC(PyNumber_Add) EXPORT_FUNC(PyNumber_And) From 48176fc72ebf515ce6e8168054f475ca6e9d8810 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 27 Mar 2024 14:55:18 +0000 Subject: [PATCH 41/79] no need for two versions of EnterScope/ExitScope --- Include/monitoring.h | 13 ------------- Python/instrumentation.c | 15 ++------------- Python/pylifecycle-c98da669.o.tmp | 0 Python/pystate-0cb7e25d.o.tmp | 0 4 files changed, 2 insertions(+), 26 deletions(-) create mode 100644 Python/pylifecycle-c98da669.o.tmp create mode 100644 Python/pystate-0cb7e25d.o.tmp diff --git a/Include/monitoring.h b/Include/monitoring.h index 3e56f594790cb74..abf80087f3ff773 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -96,19 +96,6 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike } -static inline void -PyUnstable_Monitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) -{ - _PyMonitoring_EnterScope(state_array, version, event_types, length); -} - -static inline void -PyUnstable_Monitoring_ExitScope(void) -{ - _PyMonitoring_ExitScope(); -} - static inline int PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 40802a571af172a..80f40f1769f17ce 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2344,7 +2344,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs } void -_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); @@ -2361,7 +2361,7 @@ _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, } void -_PyMonitoring_ExitScope(void) +PyMonitoring_ExitScope(void) { } @@ -2543,17 +2543,6 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik /******************* Public API *******************/ -void -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) -{ - _PyMonitoring_EnterScope(state_array, version, event_types, length); -} - -void -PyMonitoring_ExitScope(void) -{ -} #define IF_ACTIVE(STATE, X) \ if ((STATE)->active) { \ diff --git a/Python/pylifecycle-c98da669.o.tmp b/Python/pylifecycle-c98da669.o.tmp new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/Python/pystate-0cb7e25d.o.tmp b/Python/pystate-0cb7e25d.o.tmp new file mode 100644 index 000000000000000..e69de29bb2d1d64 From c52dddcb2c838401b9ca23488c4b46b9bb41e1c5 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 28 Mar 2024 11:29:59 +0000 Subject: [PATCH 42/79] Revert "update limited API" This reverts commit c0bcc2205e8038af91821bdbefcaf9c3090deabd. --- Doc/data/stable_abi.dat | 19 -------------- Lib/test/test_stable_abi_ctypes.py | 19 -------------- Misc/stable_abi.toml | 40 ------------------------------ PC/python3dll.c | 19 -------------- 4 files changed, 97 deletions(-) diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 0132d3527aa8361..2763bea5137cc72 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -433,25 +433,6 @@ function,PyModule_New,3.2,, function,PyModule_NewObject,3.7,, function,PyModule_SetDocString,3.7,, var,PyModule_Type,3.2,, -function,PyMonitoring_EnterScope,3.13,, -function,PyMonitoring_ExitScope,3.13,, -function,PyMonitoring_FireBranchEvent,3.13,, -function,PyMonitoring_FireCRaiseEvent,3.13,, -function,PyMonitoring_FireCReturnEvent,3.13,, -function,PyMonitoring_FireCallEvent,3.13,, -function,PyMonitoring_FireExceptionHandledEvent,3.13,, -function,PyMonitoring_FireInstructionEvent,3.13,, -function,PyMonitoring_FireJumpEvent,3.13,, -function,PyMonitoring_FireLineEvent,3.13,, -function,PyMonitoring_FirePyResumeEvent,3.13,, -function,PyMonitoring_FirePyReturnEvent,3.13,, -function,PyMonitoring_FirePyStartEvent,3.13,, -function,PyMonitoring_FirePyThrowEvent,3.13,, -function,PyMonitoring_FirePyUnwindEvent,3.13,, -function,PyMonitoring_FirePyYieldEvent,3.13,, -function,PyMonitoring_FireRaiseEvent,3.13,, -function,PyMonitoring_FireReraiseEvent,3.13,, -function,PyMonitoring_FireStopIterationEvent,3.13,, function,PyNumber_Absolute,3.2,, function,PyNumber_Add,3.2,, function,PyNumber_And,3.2,, diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 55f2646dffc046f..d0e4f3c71c15e07 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -464,25 +464,6 @@ def test_windows_feature_macros(self): "PyModule_NewObject", "PyModule_SetDocString", "PyModule_Type", - "PyMonitoring_EnterScope", - "PyMonitoring_ExitScope", - "PyMonitoring_FireBranchEvent", - "PyMonitoring_FireCRaiseEvent", - "PyMonitoring_FireCReturnEvent", - "PyMonitoring_FireCallEvent", - "PyMonitoring_FireExceptionHandledEvent", - "PyMonitoring_FireInstructionEvent", - "PyMonitoring_FireJumpEvent", - "PyMonitoring_FireLineEvent", - "PyMonitoring_FirePyResumeEvent", - "PyMonitoring_FirePyReturnEvent", - "PyMonitoring_FirePyStartEvent", - "PyMonitoring_FirePyThrowEvent", - "PyMonitoring_FirePyUnwindEvent", - "PyMonitoring_FirePyYieldEvent", - "PyMonitoring_FireRaiseEvent", - "PyMonitoring_FireReraiseEvent", - "PyMonitoring_FireStopIterationEvent", "PyNumber_Absolute", "PyNumber_Add", "PyNumber_And", diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 2ceea2b81cdeaea..14dda7db1c323e2 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2506,43 +2506,3 @@ added = '3.13' [function.PyType_GetModuleByDef] added = '3.13' - -# Add API for Monitoring in Python 3.13 (https://github.com/python/cpython/issues/111997) -[function.PyMonitoring_EnterScope] - added = '3.13' -[function.PyMonitoring_ExitScope] - added = '3.13' -[function.PyMonitoring_FireBranchEvent] - added = '3.13' -[function.PyMonitoring_FireCRaiseEvent] - added = '3.13' -[function.PyMonitoring_FireCReturnEvent] - added = '3.13' -[function.PyMonitoring_FireCallEvent] - added = '3.13' -[function.PyMonitoring_FireExceptionHandledEvent] - added = '3.13' -[function.PyMonitoring_FireInstructionEvent] - added = '3.13' -[function.PyMonitoring_FireJumpEvent] - added = '3.13' -[function.PyMonitoring_FireLineEvent] - added = '3.13' -[function.PyMonitoring_FirePyResumeEvent] - added = '3.13' -[function.PyMonitoring_FirePyReturnEvent] - added = '3.13' -[function.PyMonitoring_FirePyStartEvent] - added = '3.13' -[function.PyMonitoring_FirePyThrowEvent] - added = '3.13' -[function.PyMonitoring_FirePyUnwindEvent] - added = '3.13' -[function.PyMonitoring_FirePyYieldEvent] - added = '3.13' -[function.PyMonitoring_FireRaiseEvent] - added = '3.13' -[function.PyMonitoring_FireReraiseEvent] - added = '3.13' -[function.PyMonitoring_FireStopIterationEvent] - added = '3.13' diff --git a/PC/python3dll.c b/PC/python3dll.c index 8223e98be206f68..c6fdc0bd73b9fe7 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -409,25 +409,6 @@ EXPORT_FUNC(PyModule_New) EXPORT_FUNC(PyModule_NewObject) EXPORT_FUNC(PyModule_SetDocString) EXPORT_FUNC(PyModuleDef_Init) -EXPORT_FUNC(PyMonitoring_EnterScope) -EXPORT_FUNC(PyMonitoring_ExitScope) -EXPORT_FUNC(PyMonitoring_FireBranchEvent) -EXPORT_FUNC(PyMonitoring_FireCallEvent) -EXPORT_FUNC(PyMonitoring_FireCRaiseEvent) -EXPORT_FUNC(PyMonitoring_FireCReturnEvent) -EXPORT_FUNC(PyMonitoring_FireExceptionHandledEvent) -EXPORT_FUNC(PyMonitoring_FireInstructionEvent) -EXPORT_FUNC(PyMonitoring_FireJumpEvent) -EXPORT_FUNC(PyMonitoring_FireLineEvent) -EXPORT_FUNC(PyMonitoring_FirePyResumeEvent) -EXPORT_FUNC(PyMonitoring_FirePyReturnEvent) -EXPORT_FUNC(PyMonitoring_FirePyStartEvent) -EXPORT_FUNC(PyMonitoring_FirePyThrowEvent) -EXPORT_FUNC(PyMonitoring_FirePyUnwindEvent) -EXPORT_FUNC(PyMonitoring_FirePyYieldEvent) -EXPORT_FUNC(PyMonitoring_FireRaiseEvent) -EXPORT_FUNC(PyMonitoring_FireReraiseEvent) -EXPORT_FUNC(PyMonitoring_FireStopIterationEvent) EXPORT_FUNC(PyNumber_Absolute) EXPORT_FUNC(PyNumber_Add) EXPORT_FUNC(PyNumber_And) From 69cfe88f9a73a44b9a7d5ebfefc4a4b752d173c0 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 28 Mar 2024 11:55:05 +0000 Subject: [PATCH 43/79] remove stable version. Rename Unstable functions --- Include/cpython/monitoring.h | 4 +- Include/monitoring.h | 132 +++++---------------- Lib/test/test_monitoring.py | 88 +++++++------- Modules/_testcapi/monitoring.c | 204 +++++++++------------------------ Python/instrumentation.c | 129 --------------------- 5 files changed, 126 insertions(+), 431 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 362fdf5e99ef80a..b2e47b27c779a88 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -5,11 +5,11 @@ #ifndef Py_LIMITED_API PyAPI_FUNC(void) -_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) -_PyMonitoring_ExitScope(void); +PyMonitoring_ExitScope(void); PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index abf80087f3ff773..0c3c42f797e87b5 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -14,76 +14,6 @@ typedef struct _PyMonitoringState { # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H -PyAPI_FUNC(void) -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); - -PyAPI_FUNC(void) -PyMonitoring_ExitScope(void); - -PyAPI_FUNC(int) -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -PyAPI_FUNC(int) -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -PyAPI_FUNC(int) -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - -PyAPI_FUNC(int) -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno); - -PyAPI_FUNC(int) -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -PyAPI_FUNC(int) -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); #ifndef Py_LIMITED_API @@ -97,7 +27,7 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike static inline int -PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PYMONITORING_IF_ACTIVE( state, @@ -105,7 +35,7 @@ PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PYMONITORING_IF_ACTIVE( state, @@ -113,8 +43,8 @@ PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *code } static inline int -PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PYMONITORING_IF_ACTIVE( state, @@ -122,8 +52,8 @@ PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *code } static inline int -PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PYMONITORING_IF_ACTIVE( state, @@ -131,8 +61,8 @@ PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0) { _PYMONITORING_IF_ACTIVE( state, @@ -140,8 +70,8 @@ PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike } static inline int -PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno) { _PYMONITORING_IF_ACTIVE( state, @@ -149,7 +79,7 @@ PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike } static inline int -PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PYMONITORING_IF_ACTIVE( state, @@ -157,8 +87,8 @@ PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *c } static inline int -PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( state, @@ -166,8 +96,8 @@ PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike } static inline int -PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( state, @@ -175,8 +105,8 @@ PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codeli } static inline int -PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PYMONITORING_IF_ACTIVE( state, @@ -184,8 +114,8 @@ PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -193,8 +123,8 @@ PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -202,8 +132,8 @@ PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelik } static inline int -PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -211,8 +141,8 @@ PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -220,8 +150,8 @@ PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObje } static inline int -PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -229,8 +159,8 @@ PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codeli } static inline int -PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -238,8 +168,8 @@ PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *code } static inline int -PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index d8a6286030c5def..0aff35bbc071a3c 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1959,12 +1959,11 @@ def __call__(self, *args): def test_fire_event(self): for expected, event, function, *args in self.cases: - for unstable in (0, 1): - offset = 0 - self.codelike = _testcapi.CodeLike(1) - with self.subTest(function.__name__, unstable=unstable): - args_ = (self.codelike, 0, unstable) + tuple(args) - self.check_event_count(event, function, args_, expected) + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__): + args_ = (self.codelike, 0) + tuple(args) + self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, E.EXCEPTION_HANDLED, E.PY_UNWIND } @@ -2006,46 +2005,43 @@ def check_disable(self, event, func, args, expected): def test_disable_event(self): for expected, event, function, *args in self.cases: - for unstable in (0, 1): - offset = 0 - self.codelike = _testcapi.CodeLike(2) - with self.subTest(function.__name__, unstable=unstable): - args_ = (self.codelike, 0, unstable) + tuple(args) - self.check_disable(event, function, args_, expected) + offset = 0 + self.codelike = _testcapi.CodeLike(2) + with self.subTest(function.__name__): + args_ = (self.codelike, 0) + tuple(args) + self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): - for unstable in (0,1): - with self.subTest(unstable=unstable): - try: - yield_counter = CounterWithDisable() - unwind_counter = CounterWithDisable() - sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) - sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) - sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) - - yield_value = int(math.log2(E.PY_YIELD)) - unwind_value = int(math.log2(E.PY_UNWIND)) - cl = _testcapi.CodeLike(2) - with self.Scope(cl, yield_value, unwind_value): - yield_counter.count = 0 - unwind_counter.count = 0 - - _testcapi.fire_event_py_unwind(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 0) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 1) - assert(unwind_counter.count == 1) - - yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) + try: + yield_counter = CounterWithDisable() + unwind_counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) + sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) + + yield_value = int(math.log2(E.PY_YIELD)) + unwind_value = int(math.log2(E.PY_UNWIND)) + cl = _testcapi.CodeLike(2) + with self.Scope(cl, yield_value, unwind_value): + yield_counter.count = 0 + unwind_counter.count = 0 + + _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) - finally: - sys.monitoring.set_events(TEST_TOOL, 0) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 877cdb7245f8027..e3c8ead8f68d2f8 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -116,8 +116,8 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -125,13 +125,7 @@ fire_event_py_start(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyStartEvent(state, codelike, offset); - } - else { - res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - } + int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -139,8 +133,8 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -148,13 +142,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyResumeEvent(state, codelike, offset); - } - else { - res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - } + int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -162,9 +150,9 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -172,13 +160,7 @@ fire_event_py_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyReturnEvent(state, codelike, offset, retval); - } - else { - res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - } + int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -186,9 +168,9 @@ static PyObject * fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -196,13 +178,7 @@ fire_event_c_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireCReturnEvent(state, codelike, offset, retval); - } - else { - res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - } + int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -210,9 +186,9 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -220,13 +196,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyYieldEvent(state, codelike, offset, retval); - } - else { - res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - } + int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -234,9 +204,9 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &unstable, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } NULLABLE(arg0); @@ -245,13 +215,7 @@ fire_event_call(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireCallEvent(state, codelike, offset, callable, arg0); - } - else { - res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - } + int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); RETURN_INT(res == -1 ? -1 : state->active); } @@ -259,8 +223,8 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable, lineno; - if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &unstable, &lineno)) { + int offset, lineno; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -268,13 +232,7 @@ fire_event_line(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireLineEvent(state, codelike, offset, lineno); - } - else { - res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - } + int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); RETURN_INT(res == -1 ? -1 : state->active); } @@ -282,8 +240,8 @@ static PyObject * fire_event_instruction(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -291,13 +249,7 @@ fire_event_instruction(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireInstructionEvent(state, codelike, offset); - } - else { - res = PyMonitoring_FireInstructionEvent(state, codelike, offset); - } + int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -305,9 +257,9 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -315,13 +267,7 @@ fire_event_jump(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireJumpEvent(state, codelike, offset, target_offset); - } - else { - res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - } + int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -329,9 +275,9 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -339,13 +285,7 @@ fire_event_branch(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireBranchEvent(state, codelike, offset, target_offset); - } - else { - res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - } + int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -353,9 +293,9 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -364,13 +304,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyThrowEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -378,9 +312,9 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -389,13 +323,7 @@ fire_event_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireRaiseEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -403,9 +331,9 @@ static PyObject * fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -414,13 +342,7 @@ fire_event_c_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireCRaiseEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -428,9 +350,9 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -439,13 +361,7 @@ fire_event_reraise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireReraiseEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -453,9 +369,9 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -464,13 +380,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -478,9 +388,9 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -489,13 +399,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyUnwindEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -503,9 +407,9 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -514,13 +418,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireStopIterationEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 80f40f1769f17ce..1199b03307284ad 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2540,132 +2540,3 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); } - -/******************* Public API *******************/ - - -#define IF_ACTIVE(STATE, X) \ - if ((STATE)->active) { \ - return (X); \ - } \ - else { \ - return 0; \ - } - -int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); -} - -int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); -} - -int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - IF_ACTIVE(state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); -} - -int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) -{ - IF_ACTIVE(state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); -} - -int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - IF_ACTIVE(state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); -} - -int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - IF_ACTIVE(state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); -} - -int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - IF_ACTIVE(state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); -} - -int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - IF_ACTIVE(state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); -} - -#undef IF_ACTIVE From 811402a693bbf7ccb42256e43ff0c614b937cd7d Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:29:58 +0100 Subject: [PATCH 44/79] Delete Modules/_sqlite/connection-dd92fcfb.o.tmp --- Modules/_sqlite/connection-dd92fcfb.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Modules/_sqlite/connection-dd92fcfb.o.tmp diff --git a/Modules/_sqlite/connection-dd92fcfb.o.tmp b/Modules/_sqlite/connection-dd92fcfb.o.tmp deleted file mode 100644 index e69de29bb2d1d64..000000000000000 From 86d2f674ed0f0f4be9591d6932bc89ff22094cdd Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:30:18 +0100 Subject: [PATCH 45/79] Delete Modules/_testcapi/monitoring.c --- Modules/_testcapi/monitoring.c | 501 --------------------------------- 1 file changed, 501 deletions(-) delete mode 100644 Modules/_testcapi/monitoring.c diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c deleted file mode 100644 index e3c8ead8f68d2f8..000000000000000 --- a/Modules/_testcapi/monitoring.c +++ /dev/null @@ -1,501 +0,0 @@ -#include "parts.h" -#include "util.h" - -#include "monitoring.h" - -#define Py_BUILD_CORE -#include "internal/pycore_instruments.h" - -typedef struct { - PyObject_HEAD - PyMonitoringState *monitoring_states; - uint64_t version; - int num_events; - /* Other fields */ -} PyCodeLikeObject; - - -static PyObject * -CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - int num_events; - if (!PyArg_ParseTuple(args, "i", &num_events)) { - return NULL; - } - PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( - num_events, sizeof(PyMonitoringState)); - if (states == NULL) { - return NULL; - } - PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); - if (self != NULL) { - self->version = 0; - self->monitoring_states = states; - self->num_events = num_events; - } - else { - PyMem_Free(states); - } - return (PyObject *) self; -} - -static void -CodeLike_dealloc(PyCodeLikeObject *self) -{ - if (self->monitoring_states) { - PyMem_Free(self->monitoring_states); - } - Py_TYPE(self)->tp_free((PyObject *) self); -} - -static PyObject * -CodeLike_str(PyCodeLikeObject *self) -{ - PyObject *res = NULL; - PyObject *sep = NULL; - PyObject *parts = NULL; - if (self->monitoring_states) { - parts = PyList_New(0); - if (parts == NULL) { - goto end; - } - - PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); - if (heading == NULL) { - goto end; - } - int err = PyList_Append(parts, heading); - Py_DECREF(heading); - if (err < 0) { - goto end; - } - - for (int i = 0; i < self->num_events; i++) { - PyObject *part = PyUnicode_FromFormat(" %d", self->monitoring_states[i].active); - if (part == NULL) { - goto end; - } - int err = PyList_Append(parts, part); - Py_XDECREF(part); - if (err < 0) { - goto end; - } - } - sep = PyUnicode_FromString(": "); - if (sep == NULL) { - goto end; - } - res = PyUnicode_Join(sep, parts); - } -end: - Py_XDECREF(sep); - Py_XDECREF(parts); - return res; -} - -static PyTypeObject PyCodeLike_Type = { - .ob_base = PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "monitoring.CodeLike", - .tp_doc = PyDoc_STR("CodeLike objects"), - .tp_basicsize = sizeof(PyCodeLikeObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = CodeLike_new, - .tp_dealloc = (destructor) CodeLike_dealloc, - .tp_str = (reprfunc) CodeLike_str, -}; - -#define RAISE_UNLESS_CODELIKE(v) if (!Py_IS_TYPE((v), &PyCodeLike_Type)) { \ - PyErr_Format(PyExc_TypeError, "expected a code-like, got %s", Py_TYPE(v)->tp_name); \ - return NULL; \ - } - -/*******************************************************************/ - -static PyObject * -fire_event_py_start(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_resume(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_return(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_c_return(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_yield(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_call(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { - return NULL; - } - NULLABLE(arg0); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_line(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset, lineno; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_instruction(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_jump(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_branch(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_throw(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_raise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_c_raise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_reraise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_exception_handled(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_unwind(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_stop_iteration(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -/*******************************************************************/ - -static PyObject * -enter_scope(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int event1, event2=0; - Py_ssize_t num_events = PyTuple_Size(args) - 1; - if (num_events == 1) { - if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { - return NULL; - } - } - else { - assert(num_events == 2); - if (!PyArg_ParseTuple(args, "Oii", &codelike, &event1, &event2)) { - return NULL; - } - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = (PyCodeLikeObject *) codelike; - - uint8_t events[] = { event1, event2 }; - - PyMonitoring_EnterScope(cl->monitoring_states, - &cl->version, - events, - num_events); - - Py_RETURN_NONE; -} - -static PyObject * -exit_scope(PyObject *self, PyObject *args) -{ - PyMonitoring_ExitScope(); - Py_RETURN_NONE; -} - -static PyMethodDef TestMethods[] = { - {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, - {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, - {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, - {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, - {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, - {"fire_event_call", fire_event_call, METH_VARARGS}, - {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, - {"fire_event_line", fire_event_line, METH_VARARGS}, - {"fire_event_jump", fire_event_jump, METH_VARARGS}, - {"fire_event_branch", fire_event_branch, METH_VARARGS}, - {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, - {"fire_event_raise", fire_event_raise, METH_VARARGS}, - {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, - {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, - {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, - {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, - {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope", enter_scope, METH_VARARGS}, - {"exit_scope", exit_scope, METH_VARARGS}, - {NULL}, -}; - -int -_PyTestCapi_Init_Monitoring(PyObject *m) -{ - if (PyType_Ready(&PyCodeLike_Type) < 0) { - return -1; - } - if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { - Py_DECREF(m); - return -1; - } - if (PyModule_AddFunctions(m, TestMethods) < 0) { - return -1; - } - return 0; -} From e60f83f54d7cb73ead2a9e301294a7aea6f9fd1b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 1 Apr 2024 14:31:34 +0100 Subject: [PATCH 46/79] Revert "Delete Modules/_testcapi/monitoring.c" This reverts commit 86d2f674ed0f0f4be9591d6932bc89ff22094cdd. --- Modules/_testcapi/monitoring.c | 501 +++++++++++++++++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 Modules/_testcapi/monitoring.c diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c new file mode 100644 index 000000000000000..e3c8ead8f68d2f8 --- /dev/null +++ b/Modules/_testcapi/monitoring.c @@ -0,0 +1,501 @@ +#include "parts.h" +#include "util.h" + +#include "monitoring.h" + +#define Py_BUILD_CORE +#include "internal/pycore_instruments.h" + +typedef struct { + PyObject_HEAD + PyMonitoringState *monitoring_states; + uint64_t version; + int num_events; + /* Other fields */ +} PyCodeLikeObject; + + +static PyObject * +CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int num_events; + if (!PyArg_ParseTuple(args, "i", &num_events)) { + return NULL; + } + PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( + num_events, sizeof(PyMonitoringState)); + if (states == NULL) { + return NULL; + } + PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->version = 0; + self->monitoring_states = states; + self->num_events = num_events; + } + else { + PyMem_Free(states); + } + return (PyObject *) self; +} + +static void +CodeLike_dealloc(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyMem_Free(self->monitoring_states); + } + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +CodeLike_str(PyCodeLikeObject *self) +{ + PyObject *res = NULL; + PyObject *sep = NULL; + PyObject *parts = NULL; + if (self->monitoring_states) { + parts = PyList_New(0); + if (parts == NULL) { + goto end; + } + + PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); + if (heading == NULL) { + goto end; + } + int err = PyList_Append(parts, heading); + Py_DECREF(heading); + if (err < 0) { + goto end; + } + + for (int i = 0; i < self->num_events; i++) { + PyObject *part = PyUnicode_FromFormat(" %d", self->monitoring_states[i].active); + if (part == NULL) { + goto end; + } + int err = PyList_Append(parts, part); + Py_XDECREF(part); + if (err < 0) { + goto end; + } + } + sep = PyUnicode_FromString(": "); + if (sep == NULL) { + goto end; + } + res = PyUnicode_Join(sep, parts); + } +end: + Py_XDECREF(sep); + Py_XDECREF(parts); + return res; +} + +static PyTypeObject PyCodeLike_Type = { + .ob_base = PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "monitoring.CodeLike", + .tp_doc = PyDoc_STR("CodeLike objects"), + .tp_basicsize = sizeof(PyCodeLikeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = CodeLike_new, + .tp_dealloc = (destructor) CodeLike_dealloc, + .tp_str = (reprfunc) CodeLike_str, +}; + +#define RAISE_UNLESS_CODELIKE(v) if (!Py_IS_TYPE((v), &PyCodeLike_Type)) { \ + PyErr_Format(PyExc_TypeError, "expected a code-like, got %s", Py_TYPE(v)->tp_name); \ + return NULL; \ + } + +/*******************************************************************/ + +static PyObject * +fire_event_py_start(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_resume(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_c_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_yield(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_call(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { + return NULL; + } + NULLABLE(arg0); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_line(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset, lineno; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_instruction(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_jump(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_branch(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_throw(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_c_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_reraise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_exception_handled(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_unwind(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_stop_iteration(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +/*******************************************************************/ + +static PyObject * +enter_scope(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int event1, event2=0; + Py_ssize_t num_events = PyTuple_Size(args) - 1; + if (num_events == 1) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { + return NULL; + } + } + else { + assert(num_events == 2); + if (!PyArg_ParseTuple(args, "Oii", &codelike, &event1, &event2)) { + return NULL; + } + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = (PyCodeLikeObject *) codelike; + + uint8_t events[] = { event1, event2 }; + + PyMonitoring_EnterScope(cl->monitoring_states, + &cl->version, + events, + num_events); + + Py_RETURN_NONE; +} + +static PyObject * +exit_scope(PyObject *self, PyObject *args) +{ + PyMonitoring_ExitScope(); + Py_RETURN_NONE; +} + +static PyMethodDef TestMethods[] = { + {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, + {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, + {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, + {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, + {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, + {"fire_event_call", fire_event_call, METH_VARARGS}, + {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, + {"fire_event_line", fire_event_line, METH_VARARGS}, + {"fire_event_jump", fire_event_jump, METH_VARARGS}, + {"fire_event_branch", fire_event_branch, METH_VARARGS}, + {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, + {"fire_event_raise", fire_event_raise, METH_VARARGS}, + {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, + {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, + {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, + {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, + {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, + {"enter_scope", enter_scope, METH_VARARGS}, + {"exit_scope", exit_scope, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_Monitoring(PyObject *m) +{ + if (PyType_Ready(&PyCodeLike_Type) < 0) { + return -1; + } + if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { + Py_DECREF(m); + return -1; + } + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} From 8c052d3c9994d12e959e5f1578c8da8579d2d106 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:32:03 +0100 Subject: [PATCH 47/79] Delete Modules/_sqlite/cursor-8e377591.o.tmp --- Modules/_sqlite/cursor-8e377591.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Modules/_sqlite/cursor-8e377591.o.tmp diff --git a/Modules/_sqlite/cursor-8e377591.o.tmp b/Modules/_sqlite/cursor-8e377591.o.tmp deleted file mode 100644 index e69de29bb2d1d64..000000000000000 From e2f9f2f5d7c2cd4f46435b26cdb1db63a0759b3d Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:33:35 +0100 Subject: [PATCH 48/79] Delete Python/pylifecycle-c98da669.o.tmp --- Python/pylifecycle-c98da669.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Python/pylifecycle-c98da669.o.tmp diff --git a/Python/pylifecycle-c98da669.o.tmp b/Python/pylifecycle-c98da669.o.tmp deleted file mode 100644 index e69de29bb2d1d64..000000000000000 From 7b02a82f60cbf3c13837241f4376ca61dc110753 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:34:09 +0100 Subject: [PATCH 49/79] Delete Python/pystate-0cb7e25d.o.tmp --- Python/pystate-0cb7e25d.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Python/pystate-0cb7e25d.o.tmp diff --git a/Python/pystate-0cb7e25d.o.tmp b/Python/pystate-0cb7e25d.o.tmp deleted file mode 100644 index e69de29bb2d1d64..000000000000000 From 5fdce6386cc6a93fab2c22c43ccbb1e35d2be10f Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 4 Apr 2024 12:20:01 +0100 Subject: [PATCH 50/79] remove a few bits --- Include/cpython/monitoring.h | 11 ----------- Include/monitoring.h | 8 -------- Lib/test/test_monitoring.py | 1 - Modules/_testcapi/monitoring.c | 18 ------------------ Python/instrumentation.c | 10 ---------- 5 files changed, 48 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index b2e47b27c779a88..867c5101ec48d13 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -25,10 +25,6 @@ PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); @@ -37,13 +33,6 @@ PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -PyAPI_FUNC(int) -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index 0c3c42f797e87b5..701080e50db4121 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -78,14 +78,6 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int off _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } -static inline int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireInstructionEvent(state, codelike, offset)); -} - static inline int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 0aff35bbc071a3c..f29d9ef49439c21 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1918,7 +1918,6 @@ def setUp(self): ( 1, E.PY_YIELD, capi.fire_event_py_yield, 10), ( 1, E.PY_RETURN, capi.fire_event_py_return, 20), ( 2, E.CALL, capi.fire_event_call, callable, 40), - (10, E.INSTRUCTION, capi.fire_event_instruction), ( 1, E.JUMP, capi.fire_event_jump, 60), ( 1, E.BRANCH, capi.fire_event_branch, 70), ( 1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index e3c8ead8f68d2f8..b88e1477ee8c009 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -236,23 +236,6 @@ fire_event_line(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } -static PyObject * -fire_event_instruction(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - static PyObject * fire_event_jump(PyObject *self, PyObject *args) { @@ -468,7 +451,6 @@ static PyMethodDef TestMethods[] = { {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, {"fire_event_call", fire_event_call, METH_VARARGS}, - {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, {"fire_event_branch", fire_event_branch, METH_VARARGS}, diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 1199b03307284ad..e064d639878dbdf 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2431,16 +2431,6 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int of return res; } -int -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - assert(state->active); - PyObject *args[3] = { NULL, NULL, NULL }; - int res= capi_call_instrumentation(state, codelike, offset, args, 2, - PY_MONITORING_EVENT_INSTRUCTION); - return res; -} - int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) From 21537daa01b55de5bce0cbea2fa9709087fe5e05 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 4 Apr 2024 15:56:07 +0200 Subject: [PATCH 51/79] Move non-limited API to Include/cpython/ (#56) --- Include/cpython/monitoring.h | 161 +++++++++++++++++++++++++++++++++- Include/monitoring.h | 164 +---------------------------------- 2 files changed, 161 insertions(+), 164 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 867c5101ec48d13..e82073fa0fcc935 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,7 +2,12 @@ # error "this header file must not be included directly" #endif -#ifndef Py_LIMITED_API + +typedef struct _PyMonitoringState { + uint8_t active; + uint8_t opaque; +} PyMonitoringState; + PyAPI_FUNC(void) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, @@ -11,6 +16,7 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, PyAPI_FUNC(void) PyMonitoring_ExitScope(void); + PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); @@ -73,4 +79,155 @@ PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif + +#define _PYMONITORING_IF_ACTIVE(STATE, X) \ + if ((STATE)->active) { \ + return (X); \ + } \ + else { \ + return 0; \ + } + +static inline int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyStartEvent(state, codelike, offset)); +} + +static inline int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); +} + +static inline int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); +} + +static inline int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); +} + +static inline int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); +} + +static inline int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); +} + +static inline int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} + +static inline int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); +} + +static inline int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); +} + +static inline int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); +} + +#undef _PYMONITORING_IF_ACTIVE diff --git a/Include/monitoring.h b/Include/monitoring.h index 701080e50db4121..985f7f230e44e3d 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -4,174 +4,14 @@ extern "C" { #endif -typedef struct _PyMonitoringState { - uint8_t active; - uint8_t opaque; -} PyMonitoringState; - +// There is currently no limited API for monitoring +#ifndef Py_LIMITED_API # define Py_CPYTHON_MONITORING_H # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H - - -#ifndef Py_LIMITED_API - -#define _PYMONITORING_IF_ACTIVE(STATE, X) \ - if ((STATE)->active) { \ - return (X); \ - } \ - else { \ - return 0; \ - } - - -static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyStartEvent(state, codelike, offset)); -} - -static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); -} - -static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); -} - -static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); -} - -static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); -} - -static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); -} - -static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); -} - -static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); -} - -static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); -} - -static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); -} - -#undef _PYMONITORING_IF_ACTIVE #endif - #ifdef __cplusplus } #endif From aaea28e51e0fd23856f36ba3e22e8ca415a943cb Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 15:06:44 +0100 Subject: [PATCH 52/79] Petr's comments --- Include/cpython/monitoring.h | 2 +- Lib/test/test_monitoring.py | 4 ++-- Modules/_testcapi/monitoring.c | 4 ++-- Python/instrumentation.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index e82073fa0fcc935..23e07de68b06784 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -11,7 +11,7 @@ typedef struct _PyMonitoringState { PyAPI_FUNC(void) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); + const uint8_t *event_types, Py_ssize_t length); PyAPI_FUNC(void) PyMonitoring_ExitScope(void); diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index bef1517b8004c54..3cff6dd582b0e72 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1900,10 +1900,10 @@ def __init__(self, *args): self.args = args def __enter__(self): - _testcapi.enter_scope(*self.args) + _testcapi.monitoring_enter_scope(*self.args) def __exit__(self, *args): - _testcapi.exit_scope() + _testcapi.monitoring_exit_scope() def setUp(self): super(TestCApiEventGeneration, self).setUp() diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index b88e1477ee8c009..2af18828e3b63f0 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -461,8 +461,8 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope", enter_scope, METH_VARARGS}, - {"exit_scope", exit_scope, METH_VARARGS}, + {"monitoring_enter_scope", enter_scope, METH_VARARGS}, + {"monitoring_exit_scope", exit_scope, METH_VARARGS}, {NULL}, }; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 4cc00a5a6df5a9f..5819df9144576a4 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2345,7 +2345,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) + const uint8_t *event_types, Py_ssize_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2353,7 +2353,7 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, } _Py_GlobalMonitors *m = &interp->monitors; - for (uint32_t i = 0; i < length; i++) { + for (Py_ssize_t i = 0; i < length; i++) { int event = event_types[i]; state_array[i].active = m->tools[event]; } From 2f0a4d1f7beb0b75c591a0c6cd7944a6c692e78b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 16:55:05 +0100 Subject: [PATCH 53/79] int -> int32_t for offset --- Include/cpython/monitoring.h | 64 ++++++++++++++++++------------------ Python/instrumentation.c | 30 ++++++++--------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 23e07de68b06784..2b0be30a855da14 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -18,65 +18,65 @@ PyMonitoring_ExitScope(void); PyAPI_FUNC(int) -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno); PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); @@ -89,7 +89,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik } static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, @@ -97,7 +97,7 @@ PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, @@ -105,7 +105,7 @@ PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { _PYMONITORING_IF_ACTIVE( @@ -114,7 +114,7 @@ PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { _PYMONITORING_IF_ACTIVE( @@ -123,7 +123,7 @@ PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) { _PYMONITORING_IF_ACTIVE( @@ -132,7 +132,7 @@ PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int off } static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) { _PYMONITORING_IF_ACTIVE( @@ -141,7 +141,7 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int off } static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( @@ -150,7 +150,7 @@ PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int off } static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( @@ -159,7 +159,7 @@ PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int o } static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { _PYMONITORING_IF_ACTIVE( @@ -168,7 +168,7 @@ PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -177,7 +177,7 @@ PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -186,7 +186,7 @@ PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int of } static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -195,7 +195,7 @@ PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -204,7 +204,7 @@ PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -213,7 +213,7 @@ PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int o } static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -222,7 +222,7 @@ PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5819df9144576a4..191b121746d5761 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2375,7 +2375,7 @@ _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; @@ -2386,7 +2386,7 @@ _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, in int -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) { assert(state->active); @@ -2396,7 +2396,7 @@ _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, in } int -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) { assert(state->active); @@ -2406,7 +2406,7 @@ _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) { assert(state->active); @@ -2416,7 +2416,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int of } int -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) { assert(state->active); @@ -2432,7 +2432,7 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int of } int -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { assert(state->active); @@ -2442,7 +2442,7 @@ _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int of } int -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { assert(state->active); @@ -2452,7 +2452,7 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { assert(state->active); @@ -2462,7 +2462,7 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2472,7 +2472,7 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2482,7 +2482,7 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int o } int -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2492,7 +2492,7 @@ _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2502,7 +2502,7 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2512,7 +2512,7 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code } int -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2522,7 +2522,7 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, in } int -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); From 88e770f0138fb7258faedd9ff4ecb79007e3bc20 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 19:23:51 +0100 Subject: [PATCH 54/79] give EnterScope/ExitScope a return value --- Include/cpython/monitoring.h | 4 ++-- Python/instrumentation.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 2b0be30a855da14..b319d372940e720 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -9,11 +9,11 @@ typedef struct _PyMonitoringState { } PyMonitoringState; -PyAPI_FUNC(void) +PyAPI_FUNC(int) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length); -PyAPI_FUNC(void) +PyAPI_FUNC(int) PyMonitoring_ExitScope(void); diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 191b121746d5761..268840be83a6472 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2343,7 +2343,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs return err; } -void +int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) { @@ -2358,11 +2358,13 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, state_array[i].active = m->tools[event]; } *version = global_version(interp); + return 0; } -void +int PyMonitoring_ExitScope(void) { + return 0; } int From 2bed2e36d794de9ddb7e93d223ecee5d962fda38 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 19:26:02 +0100 Subject: [PATCH 55/79] add doc --- Doc/c-api/index.rst | 1 + Doc/c-api/monitoring.rst | 124 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 Doc/c-api/monitoring.rst diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst index 9a8f1507b3f4cc5..ba56b03c6ac8e7c 100644 --- a/Doc/c-api/index.rst +++ b/Doc/c-api/index.rst @@ -25,3 +25,4 @@ document the API functions in detail. memory.rst objimpl.rst apiabiversion.rst + monitoring.rst diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst new file mode 100644 index 000000000000000..9f37bd57b0beccb --- /dev/null +++ b/Doc/c-api/monitoring.rst @@ -0,0 +1,124 @@ +.. highlight:: c + +.. _monitoring: + +Added in version 3.13. + +An extension may need to interact with the event monitoring system. Subscribing +to events and registering callbacks can be done via the Python API exposed in +:mod:`sys.monitoring`. + +Generating Execution Events +=========================== + +The functions below make it possible for an extension to fire monitoring +events as it emulates the execution of Python code. Each of these functions +accepts a ``PyMonitoringState`` struct which contains concise information +about the activation state of events, as well as the event arguments, which +include a ``PyObject*`` representing the code object, the instruction offset +and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` +for details about the signatures of the different event callbacks). + +All of the functions below return 0 on success and -1 on error. + +.. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) + + Fire a ``PY_START`` event. + + +.. c:function:: int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) + + Fire a ``PY_RESUME`` event. + + +.. c:function:: int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) + + Fire a ``PY_RETURN`` event. + + +.. c:function:: int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) + + Fire a ``PY_YIELD`` event. + + +.. c:function:: int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) + + Fire a ``CALL`` event. + + +.. c:function:: int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) + + Fire a ``LINE`` event. + + +.. c:function:: int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) + + Fire a ``JUMP`` event. + + +.. c:function:: int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) + + Fire a ``BRANCH`` event. + + +.. c:function:: int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) + + Fire a ``C_RETURN`` event. + + +.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``PY_THROW`` event. + + +.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``RAISE`` event. + + +.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``C_RAISE`` event. + + +.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``RERAISE`` event. + + +.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire an ``EXCEPTION_HANDLED`` event. + + +.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``PY_UNWIND`` event. + + +.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``STOP_ITERATION`` event. + + +Managing the Monitoring State +----------------------------- + +Monitoring states can be managed with the help of monitoring scopes. A scope +would typically correspond to a python function. + +.. :c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) + + Enter a monitoring scope. ``event_types`` is an array of the event IDs for + events that may be fired from the scope. For example, the ID of a ``PY_START`` + event is the value ``PY_MONITORING_EVENT_PY_START``. + ``state_array`` is an array with a monitoring state entry for each event in + ``event_types``, it is allocated by the user but populated by + ``PyMonitoring_EnterScope`` with information about the activation state of + the event. The size of ``event_types`` (and hence also of ``state_array``) + is given in ``length``. + + The ``version`` argument is a pointer to a value which should be initialized + to 0 and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this + function to determine whether event states have changed since the previous call, + and to return quickly if they have not. From 85e90333c179a588e6863dd832f31b565e696a95 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 10:53:55 +0100 Subject: [PATCH 56/79] fix typo --- Python/instrumentation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 268840be83a6472..1820522c0ce6071 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2349,7 +2349,7 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { - return; + return 0; } _Py_GlobalMonitors *m = &interp->monitors; From 5162a039fac19a72227f1f67da30caaed69f4eff Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 11:30:40 +0100 Subject: [PATCH 57/79] update doc conf --- Doc/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/conf.py b/Doc/conf.py index f4c75c5758cb281..ed45d59f13b2a6d 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -128,6 +128,7 @@ ('c:func', 'vsnprintf'), # Standard C types ('c:type', 'FILE'), + ('c:type', 'int32_t'), ('c:type', 'int64_t'), ('c:type', 'intmax_t'), ('c:type', 'off_t'), From 0438389caab87e4a8596130f8b750a0b29de1111 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 11:44:31 +0100 Subject: [PATCH 58/79] document PyMonitoringState --- Doc/c-api/monitoring.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 9f37bd57b0beccb..d80ae942edd01df 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -19,6 +19,12 @@ include a ``PyObject*`` representing the code object, the instruction offset and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` for details about the signatures of the different event callbacks). +.. c:type:: PyMonitoringState + + Representation of the state of an event type. It is allocated by the user + while its contents are maintained by the monitoring API functions described below. + + All of the functions below return 0 on success and -1 on error. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) From 75e51034603362d6aa04b970653b053a38f469c6 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:30:09 +0100 Subject: [PATCH 59/79] Update Doc/c-api/monitoring.rst Co-authored-by: Petr Viktorin --- Doc/c-api/monitoring.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index d80ae942edd01df..eafc74d915c5600 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -25,7 +25,9 @@ for details about the signatures of the different event callbacks). while its contents are maintained by the monitoring API functions described below. -All of the functions below return 0 on success and -1 on error. +All of the functions below return 0 on success and -1 (with an exception set) on error. + +See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) From c7bd7f4d07a3be64ec6a5699f0e3ad03ece654ef Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 15:48:46 +0100 Subject: [PATCH 60/79] Petr's comments --- Include/cpython/monitoring.h | 31 ++++++++++++++++++++++++++ Include/internal/pycore_instruments.h | 32 --------------------------- Python/instrumentation.c | 4 ++-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index b319d372940e720..7a407f84310e3a8 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,6 +2,37 @@ # error "this header file must not be included directly" #endif +/* Local events. + * These require bytecode instrumentation */ + +#define PY_MONITORING_EVENT_PY_START 0 +#define PY_MONITORING_EVENT_PY_RESUME 1 +#define PY_MONITORING_EVENT_PY_RETURN 2 +#define PY_MONITORING_EVENT_PY_YIELD 3 +#define PY_MONITORING_EVENT_CALL 4 +#define PY_MONITORING_EVENT_LINE 5 +#define PY_MONITORING_EVENT_INSTRUCTION 6 +#define PY_MONITORING_EVENT_JUMP 7 +#define PY_MONITORING_EVENT_BRANCH 8 +#define PY_MONITORING_EVENT_STOP_ITERATION 9 + +#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ + ((ev) < _PY_MONITORING_LOCAL_EVENTS) + +/* Other events, mainly exceptions */ + +#define PY_MONITORING_EVENT_RAISE 10 +#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11 +#define PY_MONITORING_EVENT_PY_UNWIND 12 +#define PY_MONITORING_EVENT_PY_THROW 13 +#define PY_MONITORING_EVENT_RERAISE 14 + + +/* Ancillary events */ + +#define PY_MONITORING_EVENT_C_RETURN 15 +#define PY_MONITORING_EVENT_C_RAISE 16 + typedef struct _PyMonitoringState { uint8_t active; diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 7f84d4a763bbcf6..c98e82c8be5546a 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -13,38 +13,6 @@ extern "C" { #define PY_MONITORING_TOOL_IDS 8 -/* Local events. - * These require bytecode instrumentation */ - -#define PY_MONITORING_EVENT_PY_START 0 -#define PY_MONITORING_EVENT_PY_RESUME 1 -#define PY_MONITORING_EVENT_PY_RETURN 2 -#define PY_MONITORING_EVENT_PY_YIELD 3 -#define PY_MONITORING_EVENT_CALL 4 -#define PY_MONITORING_EVENT_LINE 5 -#define PY_MONITORING_EVENT_INSTRUCTION 6 -#define PY_MONITORING_EVENT_JUMP 7 -#define PY_MONITORING_EVENT_BRANCH 8 -#define PY_MONITORING_EVENT_STOP_ITERATION 9 - -#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ - ((ev) < _PY_MONITORING_LOCAL_EVENTS) - -/* Other events, mainly exceptions */ - -#define PY_MONITORING_EVENT_RAISE 10 -#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11 -#define PY_MONITORING_EVENT_PY_UNWIND 12 -#define PY_MONITORING_EVENT_PY_THROW 13 -#define PY_MONITORING_EVENT_RERAISE 14 - - -/* Ancillary events */ - -#define PY_MONITORING_EVENT_C_RETURN 15 -#define PY_MONITORING_EVENT_C_RAISE 16 - - typedef uint32_t _PyMonitoringEventSet; /* Tool IDs */ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 1820522c0ce6071..36ac7f0cb07ca0e 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2287,7 +2287,7 @@ PyObject *_Py_CreateMonitoringObject(void) static int -capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offset, +capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject **args, Py_ssize_t nargs, int event) { PyThreadState *tstate = _PyThreadState_GET(); @@ -2368,7 +2368,7 @@ PyMonitoring_ExitScope(void) } int -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; From 2c09788aacbdf28172ad361e8e1f759017250dfc Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 16:28:54 +0100 Subject: [PATCH 61/79] update docs --- Doc/c-api/monitoring.rst | 10 +++++++++- Doc/library/sys.monitoring.rst | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index eafc74d915c5600..78502f2e7a85ddf 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -18,6 +18,8 @@ about the activation state of events, as well as the event arguments, which include a ``PyObject*`` representing the code object, the instruction offset and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` for details about the signatures of the different event callbacks). +The ``codelike`` argument should be an instance of :class:`types.CodeType` +or of a type that emulates it. .. c:type:: PyMonitoringState @@ -119,7 +121,8 @@ would typically correspond to a python function. Enter a monitoring scope. ``event_types`` is an array of the event IDs for events that may be fired from the scope. For example, the ID of a ``PY_START`` - event is the value ``PY_MONITORING_EVENT_PY_START``. + event is the value ``PY_MONITORING_EVENT_PY_START``, which is numerically equal + to the base-2 logarithm of ``sys.monitoring.events.PY_START``. ``state_array`` is an array with a monitoring state entry for each event in ``event_types``, it is allocated by the user but populated by ``PyMonitoring_EnterScope`` with information about the activation state of @@ -130,3 +133,8 @@ would typically correspond to a python function. to 0 and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this function to determine whether event states have changed since the previous call, and to return quickly if they have not. + + +.. :c:function:: int PyMonitoring_ExitScope(void) + + Exit the last scope that was entered with :c:function:`PyMonitoring_EnterScope`. diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 4980227c60b21e3..3b8674d690db4c4 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -255,7 +255,10 @@ No events are active by default. Per code object events '''''''''''''''''''''' -Events can also be controlled on a per code object basis. +Events can also be controlled on a per code object basis. The functions +defined below which accept a :class:`types.CodeType` should be prepared +to accept a look-alike object from functions which are not defined +in Python (see :c:`_monitoring`). .. function:: get_local_events(tool_id: int, code: CodeType, /) -> int From 5936200816195b7268787c2176b310ddc3498e74 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 17:00:53 +0100 Subject: [PATCH 62/79] fix doc --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 78502f2e7a85ddf..88870ecd13812e0 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -137,4 +137,4 @@ would typically correspond to a python function. .. :c:function:: int PyMonitoring_ExitScope(void) - Exit the last scope that was entered with :c:function:`PyMonitoring_EnterScope`. + Exit the last scope that was entered with ``PyMonitoring_EnterScope``. From 3f924e44c3642a8a6d22446fde0fca18aa871ada Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:09:48 +0100 Subject: [PATCH 63/79] whitespace --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 88870ecd13812e0..10fc1a0f3781c57 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -19,7 +19,7 @@ include a ``PyObject*`` representing the code object, the instruction offset and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` for details about the signatures of the different event callbacks). The ``codelike`` argument should be an instance of :class:`types.CodeType` -or of a type that emulates it. +or of a type that emulates it. .. c:type:: PyMonitoringState From d42b7c8d267dbf71fed6013ff1b8cef2f7173e99 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:10:54 +0100 Subject: [PATCH 64/79] fix doc ref --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 3b8674d690db4c4..62885408c2a23dd 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -258,7 +258,7 @@ Per code object events Events can also be controlled on a per code object basis. The functions defined below which accept a :class:`types.CodeType` should be prepared to accept a look-alike object from functions which are not defined -in Python (see :c:`_monitoring`). +in Python (see :ref:`_monitoring`). .. function:: get_local_events(tool_id: int, code: CodeType, /) -> int From d3a5dd596e25dc7e1d4120b1c0c0325743d415ff Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:22:50 +0100 Subject: [PATCH 65/79] fix ref --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 62885408c2a23dd..0e0095e108e9c06 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -258,7 +258,7 @@ Per code object events Events can also be controlled on a per code object basis. The functions defined below which accept a :class:`types.CodeType` should be prepared to accept a look-alike object from functions which are not defined -in Python (see :ref:`_monitoring`). +in Python (see :ref:`monitoring`). .. function:: get_local_events(tool_id: int, code: CodeType, /) -> int From 0c4e65dcd940096117fc5ce5a432c139afcb940e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:44:04 +0100 Subject: [PATCH 66/79] add title --- Doc/c-api/monitoring.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 10fc1a0f3781c57..e8f90f88ab765d8 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -2,6 +2,9 @@ .. _monitoring: +Monitorong C API +================ + Added in version 3.13. An extension may need to interact with the event monitoring system. Subscribing From a59568b83717877da98b71ac8583f115209ee70e Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:36:28 +0100 Subject: [PATCH 67/79] doc update Co-authored-by: Mark Shannon --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index e8f90f88ab765d8..f07839c6920ad5b 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -122,7 +122,7 @@ would typically correspond to a python function. .. :c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) - Enter a monitoring scope. ``event_types`` is an array of the event IDs for + Enter a monitored scope. ``event_types`` is an array of the event IDs for events that may be fired from the scope. For example, the ID of a ``PY_START`` event is the value ``PY_MONITORING_EVENT_PY_START``, which is numerically equal to the base-2 logarithm of ``sys.monitoring.events.PY_START``. From 262977f137b57490a6b88713d4f2e35766a44304 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 18 Apr 2024 22:26:11 +0100 Subject: [PATCH 68/79] update doc per Petr's comments --- Doc/c-api/monitoring.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index f07839c6920ad5b..b894aca3530d846 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -137,6 +137,13 @@ would typically correspond to a python function. function to determine whether event states have changed since the previous call, and to return quickly if they have not. + The scopes referred to here are lexical scopes: a function, class or method. + ``PyMonitoring_EnterScope`` should be called whenever the lexical scope + entered. Scopes can be nested, reusing the same *state_array* and *version*, + in situations like when emulating a recursive Python function. When a code-like's + execution is paused, such as when emulating a generator, the scope needs to + be exited and re-entered. + .. :c:function:: int PyMonitoring_ExitScope(void) From 7d530b1a413767606fa68775b106fbed994e6b91 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 19 Apr 2024 10:20:20 +0100 Subject: [PATCH 69/79] reentered Co-authored-by: Mark Shannon --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index b894aca3530d846..2da926f384d75c1 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -139,7 +139,7 @@ would typically correspond to a python function. The scopes referred to here are lexical scopes: a function, class or method. ``PyMonitoring_EnterScope`` should be called whenever the lexical scope - entered. Scopes can be nested, reusing the same *state_array* and *version*, + entered. Scopes can be reentered, reusing the same *state_array* and *version*, in situations like when emulating a recursive Python function. When a code-like's execution is paused, such as when emulating a generator, the scope needs to be exited and re-entered. From 45a789583d31c6bd08ff8fec1756b6cfb55326ed Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:15:37 +0100 Subject: [PATCH 70/79] Apply suggestions from code review Co-authored-by: Petr Viktorin --- Doc/c-api/monitoring.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 2da926f384d75c1..245dc1021b5692e 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -32,6 +32,9 @@ or of a type that emulates it. All of the functions below return 0 on success and -1 (with an exception set) on error. +They should not be called with an exception set; you might want to wrap the +call in :c:func:`PyErr_GetRaisedException` and :c:func:`PyErr_SetRaisedException`. + See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) @@ -132,13 +135,14 @@ would typically correspond to a python function. the event. The size of ``event_types`` (and hence also of ``state_array``) is given in ``length``. - The ``version`` argument is a pointer to a value which should be initialized - to 0 and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this + The ``version`` argument is a pointer to a value which should be allocated + by the user together with ``state_array`` and initialized to 0, + and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this function to determine whether event states have changed since the previous call, and to return quickly if they have not. The scopes referred to here are lexical scopes: a function, class or method. - ``PyMonitoring_EnterScope`` should be called whenever the lexical scope + ``PyMonitoring_EnterScope`` should be called whenever the lexical scope is entered. Scopes can be reentered, reusing the same *state_array* and *version*, in situations like when emulating a recursive Python function. When a code-like's execution is paused, such as when emulating a generator, the scope needs to From cf9dfd09e9fd666ba10ff79488ca3e337a3bbf99 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 19 Apr 2024 12:48:05 +0100 Subject: [PATCH 71/79] whitespace --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 245dc1021b5692e..e1301859ddf517d 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -135,7 +135,7 @@ would typically correspond to a python function. the event. The size of ``event_types`` (and hence also of ``state_array``) is given in ``length``. - The ``version`` argument is a pointer to a value which should be allocated + The ``version`` argument is a pointer to a value which should be allocated by the user together with ``state_array`` and initialized to 0, and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this function to determine whether event states have changed since the previous call, From 3a6e583715edaf813ab1cb1cab1b18b2e63ce043 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 22 Apr 2024 19:42:06 +0100 Subject: [PATCH 72/79] add exceptions and disabling to doc --- Doc/c-api/monitoring.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index e1301859ddf517d..c733d80ab3d874d 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -24,6 +24,12 @@ for details about the signatures of the different event callbacks). The ``codelike`` argument should be an instance of :class:`types.CodeType` or of a type that emulates it. +The VM disables tracing when firing an event, so there is no need for user +code to do that. + +It is expected that monitoring functions are not called with an exception set, +except for those which are firing exception-related events. + .. c:type:: PyMonitoringState Representation of the state of an event type. It is allocated by the user From a704c4a88f3f4c11b3e84bb2fd98a2fcdfb3254a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 26 Apr 2024 13:40:49 +0100 Subject: [PATCH 73/79] VM takes care of exception state for exception-related events --- Lib/test/test_monitoring.py | 29 +++- Modules/_testcapi/monitoring.c | 256 ++++++++++++++++++--------------- Python/instrumentation.c | 70 +++++++-- 3 files changed, 222 insertions(+), 133 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 3cff6dd582b0e72..f656613edb8f5f1 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1928,6 +1928,7 @@ def setUp(self): ( 1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(7)), ] + def check_event_count(self, event, func, args, expected): class Counter: def __init__(self): @@ -1961,8 +1962,23 @@ def test_fire_event(self): for expected, event, function, *args in self.cases: offset = 0 self.codelike = _testcapi.CodeLike(1) + with_exc = False + with self.subTest(function.__name__): + args_ = (self.codelike, offset, with_exc) + tuple(args) + self.check_event_count(event, function, args_, expected) + + EXCEPTION_EVENTS = { E.PY_THROW, E.RAISE, E.EXCEPTION_HANDLED, + E.PY_UNWIND, E.STOP_ITERATION } + + def test_fire_event_with_exc(self): + for expected, event, function, *args in self.cases: + if not event in self.EXCEPTION_EVENTS: + continue + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with_exc = True with self.subTest(function.__name__): - args_ = (self.codelike, 0) + tuple(args) + args_ = (self.codelike, offset, with_exc) + tuple(args) self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, @@ -2008,7 +2024,7 @@ def test_disable_event(self): offset = 0 self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): - args_ = (self.codelike, 0) + tuple(args) + args_ = (self.codelike, 0, False) + tuple(args) self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): @@ -2022,24 +2038,25 @@ def test_enter_scope_two_events(self): yield_value = int(math.log2(E.PY_YIELD)) unwind_value = int(math.log2(E.PY_UNWIND)) cl = _testcapi.CodeLike(2) + common_args = (cl, 0, False) with self.Scope(cl, yield_value, unwind_value): yield_counter.count = 0 unwind_counter.count = 0 - _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + _testcapi.fire_event_py_unwind(*common_args, ValueError(42)) assert(yield_counter.count == 0) assert(unwind_counter.count == 1) - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + _testcapi.fire_event_py_yield(*common_args, ValueError(42)) assert(yield_counter.count == 1) assert(unwind_counter.count == 1) yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + _testcapi.fire_event_py_yield(*common_args, ValueError(42)) assert(yield_counter.count == 2) assert(unwind_counter.count == 1) - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + _testcapi.fire_event_py_yield(*common_args, ValueError(42)) assert(yield_counter.count == 2) assert(unwind_counter.count == 1) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 2af18828e3b63f0..7df04697f54eb38 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -112,21 +112,52 @@ static PyTypeObject PyCodeLike_Type = { /*******************************************************************/ -static PyObject * -fire_event_py_start(PyObject *self, PyObject *args) +static PyMonitoringState * +setup_fire(PyObject *codelike, int offset, bool with_exc) { - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { + PyErr_Format(PyExc_TypeError, + "expected a code-like, got %s", + Py_TYPE(codelike)->tp_name); return NULL; } - RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; + if (with_exc) { + PyErr_SetObject(PyExc_ValueError, Py_None); + } + return state; +} + +static int +teardown_fire(int res, PyMonitoringState *state, bool with_exc) +{ + if (res == -1) { + return -1; + } + if (with_exc) { + PyErr_Clear(); + } + return state->active; +} + +static PyObject * +fire_event_py_start(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + bool with_exc; + if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -134,16 +165,16 @@ fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + bool with_exc; + if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -151,17 +182,17 @@ fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -169,17 +200,17 @@ fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -187,17 +218,17 @@ fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -205,18 +236,17 @@ fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OipOO", &codelike, &offset, &with_exc, &callable, &arg0)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - NULLABLE(arg0); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -224,16 +254,16 @@ fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; int offset, lineno; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { + bool with_exc; + if (!PyArg_ParseTuple(args, "Oipi", &codelike, &offset, &with_exc, &lineno)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -241,17 +271,17 @@ fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -259,17 +289,17 @@ fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -277,18 +307,18 @@ fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -296,18 +326,18 @@ fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -315,18 +345,18 @@ fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -334,18 +364,18 @@ fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -353,18 +383,18 @@ fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -372,18 +402,18 @@ fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -391,18 +421,18 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } /*******************************************************************/ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index f36d3be04b05beb..3d80c1aeefe4292 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2569,9 +2569,15 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_THROW); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_THROW); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2579,9 +2585,15 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32 PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RAISE); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RAISE); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2589,9 +2601,15 @@ _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int3 PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_C_RAISE); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_C_RAISE); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2599,9 +2617,15 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RERAISE); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RERAISE); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2609,9 +2633,15 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_EXCEPTION_HANDLED); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_EXCEPTION_HANDLED); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2619,9 +2649,15 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, in PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_UNWIND); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_UNWIND); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2629,7 +2665,13 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_STOP_ITERATION); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_STOP_ITERATION); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } From c7de6096130ac37a7734292da7e39164aa74c070 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 26 Apr 2024 14:36:48 +0100 Subject: [PATCH 74/79] bool -> int --- Modules/_testcapi/monitoring.c | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 7df04697f54eb38..590511781507be1 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -113,7 +113,7 @@ static PyTypeObject PyCodeLike_Type = { /*******************************************************************/ static PyMonitoringState * -setup_fire(PyObject *codelike, int offset, bool with_exc) +setup_fire(PyObject *codelike, int offset, int with_exc) { if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { PyErr_Format(PyExc_TypeError, @@ -132,7 +132,7 @@ setup_fire(PyObject *codelike, int offset, bool with_exc) } static int -teardown_fire(int res, PyMonitoringState *state, bool with_exc) +teardown_fire(int res, PyMonitoringState *state, int with_exc) { if (res == -1) { return -1; @@ -148,7 +148,7 @@ fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { return NULL; } @@ -165,7 +165,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { return NULL; } @@ -182,7 +182,7 @@ fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *retval; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { return NULL; @@ -200,7 +200,7 @@ fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *retval; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { return NULL; @@ -218,7 +218,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *retval; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { return NULL; @@ -236,7 +236,7 @@ fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *callable, *arg0; if (!PyArg_ParseTuple(args, "OipOO", &codelike, &offset, &with_exc, &callable, &arg0)) { return NULL; @@ -254,7 +254,7 @@ fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; int offset, lineno; - bool with_exc; + int with_exc; if (!PyArg_ParseTuple(args, "Oipi", &codelike, &offset, &with_exc, &lineno)) { return NULL; } @@ -271,7 +271,7 @@ fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { return NULL; @@ -289,7 +289,7 @@ fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { return NULL; @@ -307,7 +307,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -326,7 +326,7 @@ fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -345,7 +345,7 @@ fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -364,7 +364,7 @@ fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -383,7 +383,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -402,7 +402,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -421,7 +421,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; From e673b5aaa28ca4a8496635fed6efa913d0db9b43 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 28 Apr 2024 16:28:19 +0100 Subject: [PATCH 75/79] exception events use 'current exception' --- Include/cpython/monitoring.h | 56 +++++-------- Lib/test/test_monitoring.py | 21 +---- Modules/_testcapi/monitoring.c | 138 ++++++++++++++------------------- Python/instrumentation.c | 123 +++++++++++++---------------- 4 files changed, 138 insertions(+), 200 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 7a407f84310e3a8..efb9ec0e587552c 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -83,32 +83,25 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); #define _PYMONITORING_IF_ACTIVE(STATE, X) \ @@ -199,66 +192,59 @@ PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int3 } static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); + _PyMonitoring_FirePyThrowEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); + _PyMonitoring_FireRaiseEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); + _PyMonitoring_FireReraiseEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); + _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); + _PyMonitoring_FireCRaiseEvent(state, codelike, offset)); } static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); + _PyMonitoring_FirePyUnwindEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); + _PyMonitoring_FireStopIterationEvent(state, codelike, offset)); } #undef _PYMONITORING_IF_ACTIVE diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index f656613edb8f5f1..2192a4cc03a8389 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1962,23 +1962,8 @@ def test_fire_event(self): for expected, event, function, *args in self.cases: offset = 0 self.codelike = _testcapi.CodeLike(1) - with_exc = False with self.subTest(function.__name__): - args_ = (self.codelike, offset, with_exc) + tuple(args) - self.check_event_count(event, function, args_, expected) - - EXCEPTION_EVENTS = { E.PY_THROW, E.RAISE, E.EXCEPTION_HANDLED, - E.PY_UNWIND, E.STOP_ITERATION } - - def test_fire_event_with_exc(self): - for expected, event, function, *args in self.cases: - if not event in self.EXCEPTION_EVENTS: - continue - offset = 0 - self.codelike = _testcapi.CodeLike(1) - with_exc = True - with self.subTest(function.__name__): - args_ = (self.codelike, offset, with_exc) + tuple(args) + args_ = (self.codelike, offset) + tuple(args) self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, @@ -2024,7 +2009,7 @@ def test_disable_event(self): offset = 0 self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): - args_ = (self.codelike, 0, False) + tuple(args) + args_ = (self.codelike, 0) + tuple(args) self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): @@ -2038,7 +2023,7 @@ def test_enter_scope_two_events(self): yield_value = int(math.log2(E.PY_YIELD)) unwind_value = int(math.log2(E.PY_UNWIND)) cl = _testcapi.CodeLike(2) - common_args = (cl, 0, False) + common_args = (cl, 0) with self.Scope(cl, yield_value, unwind_value): yield_counter.count = 0 unwind_counter.count = 0 diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 590511781507be1..e03987156528bcb 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -113,7 +113,7 @@ static PyTypeObject PyCodeLike_Type = { /*******************************************************************/ static PyMonitoringState * -setup_fire(PyObject *codelike, int offset, int with_exc) +setup_fire(PyObject *codelike, int offset, PyObject *exc) { if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { PyErr_Format(PyExc_TypeError, @@ -125,21 +125,19 @@ setup_fire(PyObject *codelike, int offset, int with_exc) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - if (with_exc) { - PyErr_SetObject(PyExc_ValueError, Py_None); + if (exc != NULL) { + PyErr_SetRaisedException(Py_NewRef(exc)); } return state; } static int -teardown_fire(int res, PyMonitoringState *state, int with_exc) +teardown_fire(int res, PyMonitoringState *state) { if (res == -1) { return -1; } - if (with_exc) { - PyErr_Clear(); - } + PyErr_Clear(); return state->active; } @@ -148,16 +146,15 @@ fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; - if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -165,16 +162,15 @@ fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; - if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -182,17 +178,16 @@ fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -200,17 +195,16 @@ fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -218,17 +212,16 @@ fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -236,17 +229,16 @@ fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OipOO", &codelike, &offset, &with_exc, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -254,16 +246,15 @@ fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; int offset, lineno; - int with_exc; - if (!PyArg_ParseTuple(args, "Oipi", &codelike, &offset, &with_exc, &lineno)) { + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -271,17 +262,16 @@ fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -289,17 +279,16 @@ fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -307,18 +296,17 @@ fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -326,18 +314,17 @@ fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -345,18 +332,17 @@ fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -364,18 +350,17 @@ fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -383,18 +368,17 @@ fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -402,18 +386,17 @@ fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -421,18 +404,17 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } /*******************************************************************/ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 3d80c1aeefe4292..26fcec8c77c032e 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2564,114 +2564,99 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int PY_MONITORING_EVENT_C_RETURN); } -int -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) -{ - assert(state->active); +static inline PyObject * +exception_event_setup(void) { PyObject *exc = PyErr_GetRaisedException(); + assert(exc != NULL); + return exc; +} - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_THROW); - if (res >= 0) { + +static inline int +exception_event_teardown(int err, PyObject *exc) { + if (err == 0) { PyErr_SetRaisedException(exc); } - return res; + else { + assert(PyErr_Occurred()); + Py_DECREF(exc); + } + return err; } int -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_THROW); + return exception_event_teardown(err, exc); +} - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, +int +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) +{ + assert(state->active); + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RAISE); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_C_RAISE); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RERAISE); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_EXCEPTION_HANDLED); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_UNWIND); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } From 5f00efbc15de4773136233f1e37d16ca6f7f9b78 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 28 Apr 2024 16:33:16 +0100 Subject: [PATCH 76/79] update doc --- Doc/c-api/monitoring.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index c733d80ab3d874d..f1e7351978cc7eb 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -28,7 +28,9 @@ The VM disables tracing when firing an event, so there is no need for user code to do that. It is expected that monitoring functions are not called with an exception set, -except for those which are firing exception-related events. +except for those which are firing exception-related events. In the latter case, +it is assumed that the event related to the current exception +(the one returned from :c:func:`PyErr_GetRaisedException`). .. c:type:: PyMonitoringState @@ -38,9 +40,6 @@ except for those which are firing exception-related events. All of the functions below return 0 on success and -1 (with an exception set) on error. -They should not be called with an exception set; you might want to wrap the -call in :c:func:`PyErr_GetRaisedException` and :c:func:`PyErr_SetRaisedException`. - See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) @@ -88,37 +87,37 @@ See :mod:`sys.monitoring` for descriptions of the events. Fire a ``C_RETURN`` event. -.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``PY_THROW`` event. -.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``RAISE`` event. -.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``C_RAISE`` event. -.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``RERAISE`` event. -.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire an ``EXCEPTION_HANDLED`` event. -.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``PY_UNWIND`` event. -.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``STOP_ITERATION`` event. From 69e900ec35e6dd6ac97a2b93fd88ae6b2b57d161 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 29 Apr 2024 15:08:48 +0100 Subject: [PATCH 77/79] raise on missing exception --- Lib/test/test_monitoring.py | 23 ++++++++++- Python/instrumentation.c | 78 ++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 2192a4cc03a8389..66aaa09c2c9a036 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1946,8 +1946,14 @@ def __call__(self, *args): event_value = int(math.log2(event)) with self.Scope(self.codelike, event_value): counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) + try: + func(*args) + except ValueError as e: + self.assertIsInstance(expected, ValueError) + self.assertEqual(str(e), str(expected)) + return + else: + self.assertEqual(counter.count, expected) prev = sys.monitoring.register_callback(TEST_TOOL, event, None) with self.Scope(self.codelike, event_value): @@ -1966,6 +1972,19 @@ def test_fire_event(self): args_ = (self.codelike, offset) + tuple(args) self.check_event_count(event, function, args_, expected) + def test_missing_exception(self): + for _, event, function, *args in self.cases: + if not (args and isinstance(args[-1], BaseException)): + continue + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__): + args_ = (self.codelike, offset) + tuple(args[:-1]) + (None,) + evt = int(math.log2(event)) + expected = ValueError(f"Firing event {evt} with no exception set") + self.check_event_count(event, function, args_, expected) + + CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, E.EXCEPTION_HANDLED, E.PY_UNWIND } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 26fcec8c77c032e..4d38c10690cc083 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2564,11 +2564,16 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int PY_MONITORING_EVENT_C_RETURN); } -static inline PyObject * -exception_event_setup(void) { - PyObject *exc = PyErr_GetRaisedException(); - assert(exc != NULL); - return exc; +static inline int +exception_event_setup(PyObject **exc, int event) { + *exc = PyErr_GetRaisedException(); + if (*exc == NULL) { + PyErr_Format(PyExc_ValueError, + "Firing event %d with no exception set", + event); + return -1; + } + return 0; } @@ -2587,76 +2592,97 @@ exception_event_teardown(int err, PyObject *exc) { int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_PY_THROW; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_THROW); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_RAISE; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RAISE); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_C_RAISE; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_C_RAISE); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_RERAISE; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RERAISE); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_EXCEPTION_HANDLED; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_EXCEPTION_HANDLED); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_PY_UNWIND; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_UNWIND); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_STOP_ITERATION; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_STOP_ITERATION); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } From 841eb6c09b6cd2ebbe9a174838fc3cf9d8587e6a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 29 Apr 2024 15:09:34 +0100 Subject: [PATCH 78/79] typo in doc --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index f1e7351978cc7eb..3f128a534962aa3 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -29,7 +29,7 @@ code to do that. It is expected that monitoring functions are not called with an exception set, except for those which are firing exception-related events. In the latter case, -it is assumed that the event related to the current exception +it is assumed that the event relates to the current exception (the one returned from :c:func:`PyErr_GetRaisedException`). .. c:type:: PyMonitoringState From 2840f12a12f6738d5575f0820cac551eaca60686 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 29 Apr 2024 15:59:12 +0100 Subject: [PATCH 79/79] Petr's comments --- Doc/c-api/monitoring.rst | 27 +++++++----- Modules/_testcapi/monitoring.c | 76 ++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 3f128a534962aa3..763ec8ef761e4eb 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -27,10 +27,8 @@ or of a type that emulates it. The VM disables tracing when firing an event, so there is no need for user code to do that. -It is expected that monitoring functions are not called with an exception set, -except for those which are firing exception-related events. In the latter case, -it is assumed that the event relates to the current exception -(the one returned from :c:func:`PyErr_GetRaisedException`). +Monitoring functions should not be called with an exception set, +except those listed below as working with the current exception. .. c:type:: PyMonitoringState @@ -89,37 +87,44 @@ See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``PY_THROW`` event. + Fire a ``PY_THROW`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``RAISE`` event. + Fire a ``RAISE`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``C_RAISE`` event. + Fire a ``C_RAISE`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``RERAISE`` event. + Fire a ``RERAISE`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire an ``EXCEPTION_HANDLED`` event. + Fire an ``EXCEPTION_HANDLED`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``PY_UNWIND`` event. + Fire a ``PY_UNWIND`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``STOP_ITERATION`` event. + Fire a ``STOP_ITERATION`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). Managing the Monitoring State diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index e03987156528bcb..aa90cfc06c1536f 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -115,12 +115,7 @@ static PyTypeObject PyCodeLike_Type = { static PyMonitoringState * setup_fire(PyObject *codelike, int offset, PyObject *exc) { - if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { - PyErr_Format(PyExc_TypeError, - "expected a code-like, got %s", - Py_TYPE(codelike)->tp_name); - return NULL; - } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -132,11 +127,19 @@ setup_fire(PyObject *codelike, int offset, PyObject *exc) } static int -teardown_fire(int res, PyMonitoringState *state) +teardown_fire(int res, PyMonitoringState *state, PyObject *exception) { if (res == -1) { return -1; } + if (exception) { + assert(PyErr_Occurred()); + assert(((PyObject*)Py_TYPE(exception)) == PyErr_Occurred()); + } + + else { + assert(!PyErr_Occurred()); + } PyErr_Clear(); return state->active; } @@ -149,12 +152,13 @@ fire_event_py_start(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -165,12 +169,13 @@ fire_event_py_resume(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -182,12 +187,13 @@ fire_event_py_return(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -199,12 +205,13 @@ fire_event_c_return(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -216,12 +223,13 @@ fire_event_py_yield(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -233,12 +241,13 @@ fire_event_call(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -249,12 +258,13 @@ fire_event_line(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -266,12 +276,13 @@ fire_event_jump(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -283,12 +294,13 @@ fire_event_branch(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -306,7 +318,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -324,7 +336,7 @@ fire_event_raise(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireRaiseEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -342,7 +354,7 @@ fire_event_c_raise(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -360,7 +372,7 @@ fire_event_reraise(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireReraiseEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -378,7 +390,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -396,7 +408,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -414,7 +426,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } /*******************************************************************/