Skip to content
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

pdb continue followed by an exception in the same frame shows incorrect frame linenumber #70966

Closed
SriramRajagopalan mannequin opened this issue Apr 16, 2016 · 7 comments
Labels
3.7 (EOL) end of life 3.8 only security fixes 3.9 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@SriramRajagopalan
Copy link
Mannequin

SriramRajagopalan mannequin commented Apr 16, 2016

BPO 26779
Nosy @birkenfeld, @orsenthil, @xdegaye, @romuald
Files
  • bdbfix.patch: Fixes the issue with bdb set_continue
  • 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 2016-04-16.13:08:12.590>
    labels = ['3.7', '3.8', 'type-bug', 'library', '3.9']
    title = 'pdb continue followed by an exception in the same frame shows incorrect frame linenumber'
    updated_at = <Date 2021-04-19.13:32:12.143>
    user = 'https://bugs.python.org/SriramRajagopalan'

    bugs.python.org fields:

    activity = <Date 2021-04-19.13:32:12.143>
    actor = 'Romuald'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2016-04-16.13:08:12.590>
    creator = 'Sriram Rajagopalan'
    dependencies = []
    files = ['42508']
    hgrepos = []
    issue_num = 26779
    keywords = ['patch']
    message_count = 6.0
    messages = ['263553', '265833', '266170', '267239', '391377', '391378']
    nosy_count = 6.0
    nosy_names = ['georg.brandl', 'orsenthil', 'xdegaye', 'Romuald', 'Sriram Rajagopalan', 'bglsriram']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue26779'
    versions = ['Python 2.7', 'Python 3.5', 'Python 3.6', 'Python 3.7', 'Python 3.8', 'Python 3.9']

    @SriramRajagopalan
    Copy link
    Mannequin Author

    SriramRajagopalan mannequin commented Apr 16, 2016

    Consider this simple python program -

    1 #!/usr/bin/python
    2
    3 import pdb
    4 import sys
    5 import traceback
    6
    7 def trace_exception( type, value, tb ):
    8 traceback.print_tb( tb )
    9 pdb.post_mortem( tb )
    10
    11 sys.excepthook = trace_exception
    12
    13 def func():
    14 print ( "Am here in func" )
    15 pdb.set_trace()
    16 print ( "Am here after pdb" )
    17 print ( "Am going to assert now" )
    18 assert False
    19 print ( "Am here after exception" )
    20
    21 def main():
    22 func()
    23
    24 if __name__ == "__main__":
    25 main()

    On running this program -

    % ./python /tmp/test.py
    Am here in func
    > /tmp/test.py(16)func()
    -> print ( "Am here after pdb" )
    (Pdb) c
    Am here after pdb
    Am going to assert now
      File "/tmp/test.py", line 25, in <module>
        main()
      File "/tmp/test.py", line 22, in main
        func()
      File "/tmp/test.py", line 16, in func
        print ( "Am here after pdb" )
    > /tmp/test.py(16)func()
    -> print ( "Am here after pdb" ) >>>> This should have been at the line corresponding to "Am going to assert now"
    (Pdb)

    This seems to be an bug ( due to a performance consideration ) with the way python bdb's set_continue() has been implemented -

    https://hg.python.org/cpython/file/2.7/Lib/bdb.py#l227

        def set_continue(self):
            # Don't stop except at breakpoints or when finished
            self._set_stopinfo(self.botframe, None, -1)
            if not self.breaks:
                # no breakpoints; run without debugger overhead
                sys.settrace(None)
                frame = sys._getframe().f_back
                while frame and frame is not self.botframe:
                    del frame.f_trace
                    frame = frame.f_back

    Basically what happens after "c" in a "(Pdb)" prompt is that bdb optimizes for the case where there are no more break points found by cleaning up the trace callback from all the frames.

    However, all of this happens in the context of tracing itself and hence the trace_dispatch function in https://hg.python.org/cpython/file/2.7/Lib/bdb.py#l45 still returns back the trace_dispatch as the new system trace function. For more details on sys.settrace(), check https://docs.python.org/2/library/sys.html#sys.settrace

    Check, the function trace_trampoline at https://hg.python.org/cpython/file/2.7/Python/sysmodule.c#l353
    which sets f->f_trace back to result at https://hg.python.org/cpython/file/2.7/Python/sysmodule.c#l377

    This seems to be an bug ( due to a performance consideration ) with the way python bdb's set_continue() has been implemented -

    https://hg.python.org/cpython/file/2.7/Lib/bdb.py#l227

        def set_continue(self):
            # Don't stop except at breakpoints or when finished
            self._set_stopinfo(self.botframe, None, -1)
            if not self.breaks:
                # no breakpoints; run without debugger overhead
                sys.settrace(None)
                frame = sys._getframe().f_back
                while frame and frame is not self.botframe:
                    del frame.f_trace
                    frame = frame.f_back

    Basically what happens after "c" in a "(Pdb)" prompt is that bdb optimizes for the case where there are no more break points found by cleaning up the trace callback from all the frames.

    However, all of this happens in the context of tracing itself and hence the trace_dispatch function in https://hg.python.org/cpython/file/2.7/Lib/bdb.py#l45 still returns back the trace_dispatch as the new system trace function. For more details on sys.settrace(), check https://docs.python.org/2/library/sys.html#sys.settrace

    Check, the function trace_trampoline at https://hg.python.org/cpython/file/2.7/Python/sysmodule.c#l353
    which sets f->f_trace back to result at https://hg.python.org/cpython/file/2.7/Python/sysmodule.c#l377

    Now, check the function PyFrame_GetLineNumber() which is used by the traceback to get the frame line number https://hg.python.org/cpython/file/2.7/Objects/frameobject.c#l63

    int
    PyFrame_GetLineNumber(PyFrameObject *f)
    {
        if (f->f_trace)
            return f->f_lineno;
        else
            return PyCode_Addr2Line(f->f_code, f->f_lasti);
    }

    Basically this function returns back the stored f->f_lineno in case the f->f_trace is enabled.

    The fix is fortunately simple -

    Just set self.trace_dispatch to None if pdb set_continue decides to run without debugger overhead.

    @SriramRajagopalan SriramRajagopalan mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Apr 16, 2016
    @bglsriram
    Copy link
    Mannequin

    bglsriram mannequin commented May 18, 2016

    ping

    @bglsriram
    Copy link
    Mannequin

    bglsriram mannequin commented May 23, 2016

    ping.

    Gentle reminder to review the patch

    @xdegaye
    Copy link
    Mannequin

    xdegaye mannequin commented Jun 4, 2016

    See also bpo-24565.

    @romuald
    Copy link
    Mannequin

    romuald mannequin commented Apr 19, 2021

    Ran into a similar issue today

    This issue (and mine is fixed) in python 3.10. Most probaly related to bpo-24565 fix

    @romuald romuald mannequin added 3.7 (EOL) end of life 3.8 only security fixes 3.9 only security fixes labels Apr 19, 2021
    @romuald
    Copy link
    Mannequin

    romuald mannequin commented Apr 19, 2021

    I meant: this issue is fixed in 3.10

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @erlend-aasland
    Copy link
    Contributor

    I meant: this issue is fixed in 3.10

    If this was fixed in 3.10, we can close this; 3.9 only accept security fixes now.

    @erlend-aasland erlend-aasland added the pending The issue will be closed if no feedback is provided label May 18, 2022
    @erlend-aasland erlend-aasland removed the pending The issue will be closed if no feedback is provided label May 19, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life 3.8 only security fixes 3.9 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    1 participant