Skip to content

Conversation

@P403n1x87
Copy link
Contributor

@P403n1x87 P403n1x87 commented Dec 2, 2025

We make the PY_UNWIND monitoring event available as a code-local event to allow trapping on function exit events when an exception bubbles up. This complements the PY_RETURN event by allowing to catch any function exit event.

Example

import random, sys

m, e = sys.monitoring, sys.monitoring.events

m.use_tool_id(0, "debugger")

def monitor(event):
    def _(f):
        m.register_callback(0, event, f)
    return _

@monitor(e.PY_START)
def _(*_, **__):
    print("entering", sys._getframe(1))

@monitor(e.PY_UNWIND)
def _(*_, **__):
    print("exiting ", sys._getframe(1), "with exception")

def foo():
    raise RuntimeError()

def bar():
    return foo()

def baz():
    return bar()

m.set_local_events(0, random.choice([foo, bar, baz]).__code__, e.PY_UNWIND | e.PY_START)

try:
    baz()
except Exception:
    pass

# entering <frame at 0x101602f80, file 'test_py_unwind_local.py', line 34, code baz>
# exiting  <frame at 0x101602f80, file 'test_py_unwind_local.py', line 35, code baz> with exception

We make the PY_UNWIND monitoring event available as a code-local
event to allow trapping on function exit events when an exception
bubbles up. This complements the PY_RETURN event by allowing to
catch any function exit event.
@P403n1x87 P403n1x87 changed the title Make PY_UNWIND available as a local event gh-142186: make PY_UNWIND available as a local event Dec 2, 2025
Comment on lines +27 to +33
((ev) <= PY_MONITORING_EVENT_STOP_ITERATION)

#define PY_MONITORING_EVENT_PY_UNWIND 11

#define PY_MONITORING_IS_LOCAL_EVENT(ev) \
((ev) < _PY_MONITORING_LOCAL_EVENTS)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO all these data should be encoded in a "table", e.g.

typedef struct _monitoring_event {
    int id;
    bool local;
    bool instrumented;
    char* name; // maybe
} monitoring_event_t;

monitoring_event_t MONITORING_EVENTS[] = { ... };

#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) (MONITORING_EVENTS[ev].instrumented)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant