[3.12] gh-58956: Fix a frame refleak in bdb (GH-128190) (#128953)

* [3.12] gh-58956: Fix a frame refleak in bdb (GH-128190)
(cherry picked from commit 767c89ba7c)

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
This commit is contained in:
Tian Gao 2025-01-17 14:19:37 -05:00 committed by GitHub
parent dfd75dfeed
commit f45da82c11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 56 additions and 0 deletions

View file

@ -340,6 +340,7 @@ class Bdb:
self.botframe = frame self.botframe = frame
frame = frame.f_back frame = frame.f_back
self.set_step() self.set_step()
self.enterframe = None
sys.settrace(self.trace_dispatch) sys.settrace(self.trace_dispatch)
def set_continue(self): def set_continue(self):
@ -356,6 +357,7 @@ class Bdb:
while frame and frame is not self.botframe: while frame and frame is not self.botframe:
del frame.f_trace del frame.f_trace
frame = frame.f_back frame = frame.f_back
self.enterframe = None
def set_quit(self): def set_quit(self):
"""Set quitting attribute to True. """Set quitting attribute to True.

View file

@ -281,6 +281,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
if hasattr(self, 'curframe') and self.curframe: if hasattr(self, 'curframe') and self.curframe:
self.curframe.f_globals.pop('__pdb_convenience_variables', None) self.curframe.f_globals.pop('__pdb_convenience_variables', None)
self.curframe = None self.curframe = None
self.curframe_locals = {}
self.tb_lineno.clear() self.tb_lineno.clear()
def setup(self, f, tb): def setup(self, f, tb):

View file

@ -1981,6 +1981,58 @@ def test_pdb_ambiguous_statements():
(Pdb) continue (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]>(5)frame_leaker()
-> pass
(Pdb) continue
1
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()
-> pass
(Pdb) next
--Return--
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()->None
-> pass
(Pdb) continue
1
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()
-> pass
(Pdb) return
--Return--
> <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()->None
-> pass
(Pdb) continue
1
"""
def test_pdb_issue_gh_65052(): def test_pdb_issue_gh_65052():
"""See GH-65052 """See GH-65052

View file

@ -0,0 +1 @@
Fixed a frame reference leak in :mod:`bdb`.