From f45da82c11a0fcbc28c099af27e47806f530a97b Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 17 Jan 2025 14:19:37 -0500 Subject: [PATCH] [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 767c89ba7c5a70626df6e75eb56b546bf911b997) Co-authored-by: Tian Gao --- Lib/bdb.py | 2 + Lib/pdb.py | 1 + Lib/test/test_pdb.py | 52 +++++++++++++++++++ ...4-12-23-02-09-44.gh-issue-58956.4OdMdT.rst | 1 + 4 files changed, 56 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst diff --git a/Lib/bdb.py b/Lib/bdb.py index 196e6b178cb9..3486deacd86a 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -340,6 +340,7 @@ class Bdb: self.botframe = frame frame = frame.f_back self.set_step() + self.enterframe = None sys.settrace(self.trace_dispatch) def set_continue(self): @@ -356,6 +357,7 @@ class Bdb: while frame and frame is not self.botframe: del frame.f_trace frame = frame.f_back + self.enterframe = None def set_quit(self): """Set quitting attribute to True. diff --git a/Lib/pdb.py b/Lib/pdb.py index 1e1b5ea4f0a1..2a6e994dac10 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -281,6 +281,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): 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): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index bd61de0ad349..778aa03a63ab 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1981,6 +1981,58 @@ def test_pdb_ambiguous_statements(): (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() + > (5)frame_leaker() + -> pass + (Pdb) continue + 1 + > (5)frame_leaker() + -> pass + (Pdb) next + --Return-- + > (5)frame_leaker()->None + -> pass + (Pdb) continue + 1 + > (5)frame_leaker() + -> pass + (Pdb) return + --Return-- + > (5)frame_leaker()->None + -> pass + (Pdb) continue + 1 + """ + def test_pdb_issue_gh_65052(): """See GH-65052 diff --git a/Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst b/Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst new file mode 100644 index 000000000000..b78bc5aaf442 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst @@ -0,0 +1 @@ +Fixed a frame reference leak in :mod:`bdb`. -- 2.47.3