Skip to content

Commit

Permalink
[3.13] pythongh-58956: Fix a frame refleak in bdb (pythonGH-128190) (p…
Browse files Browse the repository at this point in the history
…ython#128947)

* pythongh-58956: Fix a frame refleak in bdb (pythonGH-128190)
(cherry picked from commit 767c89b)

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
  • Loading branch information
miss-islington and gaogaotiantian authored Jan 17, 2025
1 parent 9974e71 commit dc77f19
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Lib/bdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ def set_trace(self, frame=None):
frame.f_trace_lines = True
frame = frame.f_back
self.set_stepinstr()
self.enterframe = None
sys.settrace(self.trace_dispatch)

def set_continue(self):
Expand All @@ -401,6 +402,7 @@ def set_continue(self):
for frame, (trace_lines, trace_opcodes) in self.frame_trace_lines_opcodes.items():
frame.f_trace_lines, frame.f_trace_opcodes = trace_lines, trace_opcodes
self.frame_trace_lines_opcodes = {}
self.enterframe = None

def set_quit(self):
"""Set quitting attribute to True.
Expand Down
1 change: 1 addition & 0 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ def forget(self):
if hasattr(self, 'curframe') and self.curframe:
self.curframe.f_globals.pop('__pdb_convenience_variables', None)
self.curframe = None
self.curframe_locals = {}
self.tb_lineno.clear()

def setup(self, f, tb):
Expand Down
51 changes: 51 additions & 0 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2810,6 +2810,57 @@ def test_pdb_f_trace_lines():
(Pdb) continue
"""

def test_pdb_frame_refleak():
"""
pdb should not leak reference to frames
>>> def frame_leaker(container):
... import sys
... container.append(sys._getframe())
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... pass
>>> def test_function():
... import gc
... container = []
... frame_leaker(container) # c
... print(len(gc.get_referrers(container[0])))
... container = []
... frame_leaker(container) # n c
... print(len(gc.get_referrers(container[0])))
... container = []
... frame_leaker(container) # r c
... print(len(gc.get_referrers(container[0])))
>>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
... 'continue',
... 'next',
... 'continue',
... 'return',
... 'continue',
... ]):
... test_function()
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(4)frame_leaker()
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) continue
1
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(4)frame_leaker()
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) next
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()
-> pass
(Pdb) continue
1
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(4)frame_leaker()
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) return
--Return--
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()->None
-> pass
(Pdb) continue
1
"""

def test_pdb_function_break():
"""Testing the line number of break on function
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a frame reference leak in :mod:`bdb`.

0 comments on commit dc77f19

Please sign in to comment.