Skip to content

Commit c17d30b

Browse files
[3.12] gh-58956: Set f_trace on frames with breakpoints after setting a new breakpoint (GH-124454) (#125549)
* gh-58956: Set f_trace on frames with breakpoints after setting a new breakpoint (GH-124454) (cherry picked from commit 12eaadc) Co-authored-by: Tian Gao <[email protected]>
1 parent 5431cfa commit c17d30b

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

Lib/bdb.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def __init__(self, skip=None):
3434
self.breaks = {}
3535
self.fncache = {}
3636
self.frame_returning = None
37+
self.enterframe = None
3738

3839
self._load_breaks()
3940

@@ -341,6 +342,7 @@ def set_trace(self, frame=None):
341342
342343
If frame is not specified, debugging starts from caller's frame.
343344
"""
345+
sys.settrace(None)
344346
if frame is None:
345347
frame = sys._getframe().f_back
346348
self.reset()
@@ -404,6 +406,14 @@ def set_break(self, filename, lineno, temporary=False, cond=None,
404406
return 'Line %s:%d does not exist' % (filename, lineno)
405407
self._add_to_breaks(filename, lineno)
406408
bp = Breakpoint(filename, lineno, temporary, cond, funcname)
409+
# After we set a new breakpoint, we need to search through all frames
410+
# and set f_trace to trace_dispatch if there could be a breakpoint in
411+
# that frame.
412+
frame = self.enterframe
413+
while frame:
414+
if self.break_anywhere(frame):
415+
frame.f_trace = self.trace_dispatch
416+
frame = frame.f_back
407417
return None
408418

409419
def _load_breaks(self):

Lib/test/test_pdb.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,6 +2371,36 @@ def test_issue26053(self):
23712371
self.assertRegex(res, "Restarting .* with arguments:\na b c")
23722372
self.assertRegex(res, "Restarting .* with arguments:\nd e f")
23732373

2374+
def test_issue58956(self):
2375+
# Set a breakpoint in a function that already exists on the call stack
2376+
# should enable the trace function for the frame.
2377+
script = """
2378+
import bar
2379+
def foo():
2380+
ret = bar.bar()
2381+
pass
2382+
foo()
2383+
"""
2384+
commands = """
2385+
b bar.bar
2386+
c
2387+
b main.py:5
2388+
c
2389+
p ret
2390+
quit
2391+
"""
2392+
bar = """
2393+
def bar():
2394+
return 42
2395+
"""
2396+
with open('bar.py', 'w') as f:
2397+
f.write(textwrap.dedent(bar))
2398+
self.addCleanup(os_helper.unlink, 'bar.py')
2399+
stdout, stderr = self.run_pdb_script(script, commands)
2400+
lines = stdout.splitlines()
2401+
self.assertIn('-> pass', lines)
2402+
self.assertIn('(Pdb) 42', lines)
2403+
23742404
def test_step_into_botframe(self):
23752405
# gh-125422
23762406
# pdb should not be able to step into the botframe (bdb.py)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a bug in :mod:`pdb` where sometimes the breakpoint won't trigger if it was set on a function which is already in the call stack.

0 commit comments

Comments
 (0)