Can breakpoints stop within sys.monitoring callbacks?

I’ve been experimenting with sys.monitoring using this script:

from sys import monitoring
from types import CodeType

TOOL_ID = monitoring.PROFILER_ID


def on_py_start(code: CodeType, instruction_offset: int) -> None:
    breakpoint()
    print("we've past the breakpoint")


monitoring.use_tool_id(TOOL_ID, "example-tool")
monitoring.set_events(TOOL_ID, monitoring.events.PY_START)
monitoring.register_callback(TOOL_ID, monitoring.events.PY_START, on_py_start)


def f():
    ...


f()

I added a breakpoint so that I can play with the code object and better understand what information I can gather from within a callback. However, when I run this script, the interpreter doesn’t stop at the breakpoint. Instead, it seems to register the breakpoint, continue to the end of the callback, and finally breaks before the first line of the f is called. e.g.

❯ python sample.py
we've past the breakpoint
> ~/scratch/example.py(29)f()
-> ...
(Pdb)

Do I need some additional configuration to allow breakpoints to stop within registered monitoring callbacks? Or is breaking within a callback impossible? (possibly for recursion reasons)?

My one other thought was that Pdb uses sys.settrace, which might conflict with sys.monitoring hooks. I noticed gh-120144: Make it possible to use `sys.monitoring` for bdb and make it default for pdb by gaogaotiantian · Pull Request #124533 · python/cpython · GitHub is up and ready to merge, so I checked out that branch, built a new python.exe and ran the example script again. Unfortunately, the behavior is the same and the interpreter doesn’t stop until it has exited the callback.

2 Likes

No you can’t set a breakpoint inside sys.monitoring callbacks or sys.settrace callbacks. This is to avoid infinite recursion. You can do an explicit sys.call_tracing() to achieve such purpose, but pdb at this point does not automatically support it. (pdb itself can do recursive debugging with it though, with debug command)

1 Like