]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-58956: Fix a frame refleak in bdb (GH-128190) (#128953)
authorTian Gao <gaogaotiantian@hotmail.com>
Fri, 17 Jan 2025 19:19:37 +0000 (14:19 -0500)
committerGitHub <noreply@github.com>
Fri, 17 Jan 2025 19:19:37 +0000 (14:19 -0500)
* [3.12] gh-58956: Fix a frame refleak in bdb (GH-128190)
(cherry picked from commit 767c89ba7c5a70626df6e75eb56b546bf911b997)

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
Lib/bdb.py
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst [new file with mode: 0644]

index 196e6b178cb9fd3d88f489d1df7259df21ff8df8..3486deacd86a7c63130b3324bf555c2f1cb07aa9 100644 (file)
@@ -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.
index 1e1b5ea4f0a1847c078530fcfbbf95935ef680ed..2a6e994dac10732278ff39bfa84ada68fd8ebe1e 100755 (executable)
@@ -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):
index bd61de0ad3494c54494f51574134f6707933e30b..778aa03a63ab63ad1bff993787910e07a306e126 100644 (file)
@@ -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()
+    > <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():
     """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 (file)
index 0000000..b78bc5a
--- /dev/null
@@ -0,0 +1 @@
+Fixed a frame reference leak in :mod:`bdb`.