From dc77f1914d614bab04769616d7bc6674ee723f47 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Fri, 17 Jan 2025 18:49:15 +0100 Subject: [PATCH] [3.13] gh-58956: Fix a frame refleak in bdb (GH-128190) (#128947) * 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 | 51 +++++++++++++++++++ ...4-12-23-02-09-44.gh-issue-58956.4OdMdT.rst | 1 + 4 files changed, 55 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 ece0a29fe9f3..3a4453d95f65 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -382,6 +382,7 @@ class Bdb: frame.f_trace_lines = True frame = frame.f_back self.set_stepinstr() + self.enterframe = None sys.settrace(self.trace_dispatch) def set_continue(self): @@ -401,6 +402,7 @@ class Bdb: 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. diff --git a/Lib/pdb.py b/Lib/pdb.py index 9b6dffda1cfc..cb0a3405c58e 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -383,6 +383,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 5b25f514b9e7..c34046f0e5bb 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -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() + > (4)frame_leaker() + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) continue + 1 + > (4)frame_leaker() + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) next + > (5)frame_leaker() + -> pass + (Pdb) continue + 1 + > (4)frame_leaker() + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) return + --Return-- + > (5)frame_leaker()->None + -> pass + (Pdb) continue + 1 + """ + def test_pdb_function_break(): """Testing the line number of break on function 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