Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
gh-111997: C-API for signalling monitoring events#116413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
b2d19c31b9487c150011aebc36b51ad872c34179c13c9f8bb344fd26ecaee5e5c680957661865580a9f319a1f90745a2b3ba5e7e0aa1967568aa352db4e3b899722f8445b19f33ce7aacf6e20d89b05f15f727256368b42e6d7c6a58f2bcfdb5a2860f329ae38346e8738921df5c40fc95c5275427e1163bc47df5f11cdae719e38be236b18c1eacf23f579beee637e24cd7c429c01e30df7473ef9a4a1dea138ec0bcc2248176fcc52dddc69cfe8820ce59f811402a86d2f67e60f83f8c052d3e2f9f2f7b02a82c605827a6d45c4e98827c5fdce6321537da8eac91d1956867882a205aaea28e2f0a4d188e770f2bed2e3573fbf885e90335162a030438389f53ceed75e5103c7bd7f42c0978859362003f924e4d42b7c8d3a5dd50c4e65da59568b71e6bd31ed891d262977f7d530b145a7895cf9dfd003382bc3a6e583a704c4ac7de609e673b5a5f00efb69e900e841eb6c2840f12c8499e5aa6aa8a6c65373bf84396File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -25,3 +25,4 @@ document the API functions in detail. | ||
| memory.rst | ||
| objimpl.rst | ||
| apiabiversion.rst | ||
| monitoring.rst | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| .. highlight:: c | ||
| .. _monitoring: | ||
| Monitorong C API | ||
| ================ | ||
| 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). | ||
| 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. | ||
| Monitoring functions should not be called with an exception set, | ||
| except those listed below as working with the current exception. | ||
| .. 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 (with an exception set) on error. | ||
iritkatriel marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| See :mod:`sys.monitoring` for descriptions of the events. | ||
| .. 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) | ||
| 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 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 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 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 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 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 with the current exception (as returned by | ||
| :c:func:`PyErr_GetRaisedException`). | ||
| 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 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``. | ||
| ``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 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. | ||
encukou marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. iritkatriel marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| The scopes referred to here are lexical scopes: a function, class or method. | ||
| ``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 | ||
| be exited and re-entered. | ||
| .. :c:function:: int PyMonitoring_ExitScope(void) | ||
| Exit the last scope that was entered with ``PyMonitoring_EnterScope``. | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.