Skip to content

Add Py_BREAKPOINT and sys._breakpoint hooks #53844

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

Closed
davidmalcolm opened this issue Aug 18, 2010 · 11 comments
Closed

Add Py_BREAKPOINT and sys._breakpoint hooks #53844

davidmalcolm opened this issue Aug 18, 2010 · 11 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@davidmalcolm
Copy link
Member

BPO 9635
Nosy @loewis, @pitrou, @vstinner, @davidmalcolm, @csabella
Files
  • add-sys.breakpoint.patch: Patch against py3k branch
  • py3k-add-breakpoint-2010-11-01-001.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2010-08-18.23:43:23.552>
    labels = ['interpreter-core', 'type-feature', 'library']
    title = 'Add Py_BREAKPOINT and sys._breakpoint hooks'
    updated_at = <Date 2018-02-27.20:48:25.584>
    user = 'https://github.com/davidmalcolm'

    bugs.python.org fields:

    activity = <Date 2018-02-27.20:48:25.584>
    actor = 'dmalcolm'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Interpreter Core', 'Library (Lib)']
    creation = <Date 2010-08-18.23:43:23.552>
    creator = 'dmalcolm'
    dependencies = []
    files = ['18572', '19457']
    hgrepos = []
    issue_num = 9635
    keywords = ['patch']
    message_count = 10.0
    messages = ['114301', '114303', '120174', '120175', '120241', '167169', '167623', '167751', '312605', '313024']
    nosy_count = 5.0
    nosy_names = ['loewis', 'pitrou', 'vstinner', 'dmalcolm', 'cheryl.sabella']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue9635'
    versions = ['Python 3.2', 'Python 3.3']

    @davidmalcolm
    Copy link
    Member Author

    It's sometimes useful to be able to programatically inject a breakpoint when debugging CPython.

    For example, sometimes you want a conditional breakpoint, but the logic involved is too complex to be expressed in the debugger (e.g. runtime complexity of evaluating the conditional in the debugger process, or deficiency of the debugger itself).

    I'm attaching a patch which:
      - adds a Py_BREAKPOINT macro to pyport.h   This is available as a quick and dirty way of hardcoding a breakpoint in code (e.g. in extension modules); so that when you need to you can put of these in (perhaps guarded by C-level conditionals):
           if (complex_conditional()) {
               Py_BREAKPOINT();
           }
    • when Py_BREAKPOINT is defined, adds a sys.breakpoint() method. This means that you can add C-level breakpoints to Python scripts, perhaps guarded by python-level conditionals:
      if foo and bar and not baz:
      sys.breakpoint()

    Naturally this is highly system-dependent. Only tested on Linux (Fedora 13 x86_64 with gcc-4.4.4). The Windows implementation was copied from http://bugs.python.org/issue8863 but I don't have a Windows box to test it on.

    I note that the GLib library within GNOME has a similar idea with a G_BREAKPOINT macro, which has accumulated a collection of platform-specific logic:
    http://git.gnome.org/browse/glib/tree/glib/gbacktrace.h
    (unfortunately that's LGPLv2+ licensed)

    Doesn't yet have a unit test.

    Note that when running on Linux when _not_ under a debugger, the default for SIGTRAP is to get a coredump:
    Trace/breakpoint trap (core dumped)
    so people should be strongly discouraged from adding these calls to their code.

    @davidmalcolm davidmalcolm added interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Aug 18, 2010
    @davidmalcolm
    Copy link
    Member Author

    Note that when running on Linux when _not_ under a debugger, the
    default for SIGTRAP is to get a coredump:
    Trace/breakpoint trap (core dumped)
    so people should be strongly discouraged from adding these calls to
    their code.
    Looks like Windows' DebugBreak has similar behavior here; according to:
    http://msdn.microsoft.com/en-us/library/ms679297(VS.85).aspx
    "If the process is not being debugged, the function uses the search logic of a standard exception handler. In most cases, this causes the calling process to terminate because of an unhandled breakpoint exception."

    @merwok merwok changed the title RFE(patch): add Py_BREAKPOINT and sys.breakpoint hooks Add Py_BREAKPOINT and sys.breakpoint hooks Aug 19, 2010
    @davidmalcolm
    Copy link
    Member Author

    Adding updated version of patch, which adds documentation to sys.rst and adds a unit test.

    I'm a little wary of this: it seems useful but also too much like a self-destruct button for my taste.

    @davidmalcolm
    Copy link
    Member Author

    I renamed it from sys.breakpoint to sys._breakpoint, since this is CPython-specific

    @davidmalcolm davidmalcolm changed the title Add Py_BREAKPOINT and sys.breakpoint hooks Add Py_BREAKPOINT and sys._breakpoint hooks Nov 1, 2010
    @pitrou
    Copy link
    Member

    pitrou commented Nov 2, 2010

    I would rename Py_BREAKPOINT to _Py_BREAKPOINT since we don't really want to support this. Also, why do you allow any arguments to sys._breakpoint()?

    @davidmalcolm
    Copy link
    Member Author

    Note to self: a messy way of forcing gdb to do the equivalent of a breakpoint directly from Python is:
    os.kill(os.getpid(), signal.SIGTRAP)

    @davidmalcolm
    Copy link
    Member Author

    On Tue, 2010-11-02 at 17:25 +0000, Antoine Pitrou wrote:

    Antoine Pitrou <pitrou@free.fr> added the comment:

    I would rename Py_BREAKPOINT to _Py_BREAKPOINT since we don't really want to support this. Also, why do you allow any arguments to sys._breakpoint()?
    Agreed about _Py_BREAKPOINT.

    The reason for allowing arguments to sys._breakpoint() is so that the
    developer can pass in arbitrary objects (or collections of objects),
    which can then be easily inspected from the debugger. Does that seem
    sane?

    Maybe the docs should read:

    ------
    This may be of use when tracking down bugs: the breakpoint can be
    guarded by Python-level conditionals, and supply Python-generated data::

       if foo and bar and not baz:
           sys._breakpoint(some_func(foo, bar, baz))

    In the above example, if the given python conditional holds (and no
    exception is raised calling "some_func"), execution will halt under
    the debugger within Python/sysmodule.c:sys_breakpoint, and the result of
    some_func() will be inspectable in the debugger as
    ((PyTupleObject*)args)[0]

       static PyObject *
       sys_breakpoint(PyObject *self, PyObject *args)
       {
         _Py_BREAKPOINT();
         Py_RETURN_NONE;
       }

    It can also be useful to call when debugging the CPython interpreter: if
    you add a call to this function immediately before the code of interest,
    you can step out of sys_breakpoint and then step through subsequent
    execution.
    ------

    I thought about it making it METH_O instead (to make it easier to look
    at a single object), but then you'd be forced to pass an object in when
    using it, I think (though None should work).

    @vstinner
    Copy link
    Member

    vstinner commented Aug 9, 2012

    I thought about it making it METH_O instead (to make it easier to
    look at a single object), but then you'd be forced to pass an object
    in when using it, I think (though None should work).

    I don't like this API. I really prefer METH_O because it is already very difficult to dump a Python object in a debugger (especially with gdb macros). Why not using two functions? One without argument, One with an argument.

    The sys module is maybe not the right place for such low level function. You may create a new module with a name starting with _ (ex: _python_dbg). I'm quite sure that you will find other nice functions to add if you have a module dedicated to debugging :-)

    If you don't want to create a new module, faulthandler might be used to add new debug functions.

    It's maybe unrelated, but Brian Curtin also created a module to help debugging with Visual Studio:
    https://bitbucket.org/briancurtin/minidumper/

    We may use the same module for all debugging functions? (I suppose that Brian Curtin wants to integrate its minidumper into Python 3.4.)

    Example:

    • faulthandler._breakpoint()
    • faulthandler._inspect(obj) # breakpoint with an object
    • faulthandler.enable_minidumper(...)
    • faulthandler.disable_minidumper(...)

    --

    For Power PC, the machine code to generate a breakpoint is 0x0cc00000. The instruction looks to be called twllei. Something like: "twllei reg_ZERO,trap_Cerror". Hum, it looks like there is family of instructions related to trap: all TW* instructions (twle, twlt, twge, ...).

    @csabella
    Copy link
    Contributor

    Did PEP-553 make this issue obsolete?

    @davidmalcolm
    Copy link
    Member Author

    On Fri, 2018-02-23 at 00:16 +0000, Cheryl Sabella wrote:

    Cheryl Sabella <chekat2@gmail.com> added the comment:

    Did PEP-553 make this issue obsolete?

    I *think* they have slightly different scope: if I'm reading it right,
    PEP-553 is about injecting a breakpoint into the Python debugger. This
    proposal was about injecting a lower-level breakpoint for debugging
    CPython itself (for e.g. gdb to handle).

    The idea was to make it easier to, say, step through a particular
    CPython construct at the C level by injecting a breakpoint right before
    it:

    def test_something():
      # lots of setup
      sys.c_level_breakpoint()
      # whatever comes next

    so that sys.c_level_breakpoint drops you into, say, gdb, and from there
    you can step through the following Python code at the C level, without
    having to express stepping through all the setup at the C/gdb level.

    Hope that makes sense.

    That said, I'm full-time on gcc these days, and unlikely to pursue this
    from the CPython side.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @vstinner
    Copy link
    Member

    vstinner commented Apr 2, 2025

    While the feature request is legit, there is a lack of interest to implement it and this issue is inactive for many years. I close it.

    @vstinner vstinner closed this as not planned Won't fix, can't repro, duplicate, stale Apr 2, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    4 participants