This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author xdegaye
Recipients xdegaye
Date 2011-10-14.18:56:30
SpamBayes Score 0.0
Marked as misclassified No
Message-id <1318618591.85.0.940577569218.issue13183@psf.upfronthosting.co.za>
In-reply-to
Content
Pdb skips frames after hitting a breakpoint and running step commands
that walk back the frame stack.

Run the following two tests with the two files named foo.py and bar.py:

===   foo.py   ============================================
from bar import bar

def foo():
    bar()

def nope():
    pass

def foobar():
    foo()
    nope()

foobar()

===   bar.py   ============================================
def bar():
    print('1')

===   test_1   ============================================
$ python3 --version
Python 3.2

$ python3 -m pdb foo.py
> /path/to/foo.py(1)<module>()
-> from bar import bar
(Pdb) from bar import bar
(Pdb) break bar
Breakpoint 1 at /path/to/bar.py:1
(Pdb) continue
> /path/to/bar.py(2)bar()
-> print('1')
(Pdb) step
1
--Return--
> /path/to/bar.py(2)bar()->None
-> print('1')
(Pdb) step
--Call--
> /path/to/foo.py(6)nope()
-> def nope():
(Pdb)

===   test_2   ============================================
$ python3 -m pdb foo.py
> /path/to/foo.py(1)<module>()
-> from bar import bar
(Pdb) break nope
Breakpoint 1 at /path/to/foo.py:6
(Pdb) from bar import bar
(Pdb) break bar
Breakpoint 2 at /path/to/bar.py:1
(Pdb) continue
> /path/to/bar.py(2)bar()
-> print('1')
(Pdb) step
1
--Return--
> /path/to/bar.py(2)bar()->None
-> print('1')
(Pdb) step
--Return--
> /path/to/foo.py(4)foo()->None
-> bar()
(Pdb)

===========================================================

Note: stop_here, break_anywhere and dispatch_call are methods of the
Bdb class.

test_1 fails to stop in foo() after the second 'step' command because
the trace function is not set for all the frames being created in the
foo module, since stop_here() and break_anywhere() are both False
whenever dispatch_call() is invoked in this module. So after the
second 'step' command, trace_dispatch is not invoked by the
interpreter until a new frame is created, which happens when nope() is
called.

test_2 succeeds and stops in foo() after the second 'step' command.
After setting the dummy breakpoint 1 in the foo module in test_2,
break_anywhere() becomes True in the foo module and the trace function
is set for all the frames created in this module (with an associated
performance penalty).

The problem exists in all python versions.

The attached patch fixes this problem by restoring the trace function
on returning from a frame when the command is 'step'.

The patch includes a test case.
History
Date User Action Args
2011-10-14 18:56:31xdegayesetrecipients: + xdegaye
2011-10-14 18:56:31xdegayesetmessageid: <1318618591.85.0.940577569218.issue13183@psf.upfronthosting.co.za>
2011-10-14 18:56:31xdegayelinkissue13183 messages
2011-10-14 18:56:31xdegayecreate