| 
									
										
										
										
											2024-05-04 09:23:50 +01:00
										 |  |  | #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 PyMonitoringState * | 
					
						
							|  |  |  | setup_fire(PyObject *codelike, int offset, PyObject *exc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     RAISE_UNLESS_CODELIKE(codelike); | 
					
						
							|  |  |  |     PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); | 
					
						
							|  |  |  |     assert(offset >= 0 && offset < cl->num_events); | 
					
						
							|  |  |  |     PyMonitoringState *state = &cl->monitoring_states[offset]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (exc != NULL) { | 
					
						
							|  |  |  |         PyErr_SetRaisedException(Py_NewRef(exc)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | fire_event_py_start(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *codelike; | 
					
						
							|  |  |  |     int offset; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { | 
					
						
							|  |  |  |         return 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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | fire_event_py_resume(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *codelike; | 
					
						
							|  |  |  |     int offset; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { | 
					
						
							|  |  |  |         return 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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | fire_event_line(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *codelike; | 
					
						
							|  |  |  |     int offset, lineno; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { | 
					
						
							|  |  |  |         return 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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset); | 
					
						
							|  |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyMonitoring_FireRaiseEvent(state, codelike, offset); | 
					
						
							|  |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset); | 
					
						
							|  |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyMonitoring_FireReraiseEvent(state, codelike, offset); | 
					
						
							|  |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset); | 
					
						
							|  |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset); | 
					
						
							|  |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | fire_event_stop_iteration(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *codelike; | 
					
						
							|  |  |  |     int offset; | 
					
						
							| 
									
										
										
										
											2024-05-21 16:42:51 -04:00
										 |  |  |     PyObject *value; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &value)) { | 
					
						
							| 
									
										
										
										
											2024-05-04 09:23:50 +01:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-21 16:42:51 -04:00
										 |  |  |     NULLABLE(value); | 
					
						
							|  |  |  |     PyObject *exception = NULL; | 
					
						
							| 
									
										
										
										
											2024-05-04 09:23:50 +01:00
										 |  |  |     PyMonitoringState *state = setup_fire(codelike, offset, exception); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-21 16:42:51 -04:00
										 |  |  |     int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, value); | 
					
						
							| 
									
										
										
										
											2024-05-04 09:23:50 +01:00
										 |  |  |     RETURN_INT(teardown_fire(res, state, exception)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*******************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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_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}, | 
					
						
							|  |  |  |     {"monitoring_enter_scope", enter_scope, METH_VARARGS}, | 
					
						
							|  |  |  |     {"monitoring_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; | 
					
						
							|  |  |  | } |