]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-95818: Skip incomplete frames in `PyThreadState_GetFrame` (GH-95886) (#95890)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 12 Aug 2022 18:40:49 +0000 (11:40 -0700)
committerGitHub <noreply@github.com>
Fri, 12 Aug 2022 18:40:49 +0000 (19:40 +0100)
(cherry picked from commit 1b46d118e6e72daa64b98cafddb406c68b419efa)

Co-authored-by: Mark Shannon <mark@hotpy.org>
Co-authored-by: Mark Shannon <mark@hotpy.org>
Lib/test/test_frame.py
Misc/NEWS.d/next/Core and Builtins/2022-08-11-11-01-56.gh-issue-95818.iClLdl.rst [new file with mode: 0644]
Python/pystate.c

index a715e725a7e45b17d4cbcb43ed56e421e27678c1..9fab17684eec02b25c66afa4bf54b92a1f880e36 100644 (file)
@@ -235,6 +235,28 @@ class ReprTest(unittest.TestCase):
                          r"^<frame at 0x[0-9a-fA-F]+, file %s, line %d, code inner>$"
                          % (file_repr, offset + 5))
 
+class TestIncompleteFrameAreInvisible(unittest.TestCase):
+
+    def test_issue95818(self):
+        #See GH-95818 for details
+        import gc
+        self.addCleanup(gc.set_threshold, *gc.get_threshold())
+
+        gc.set_threshold(1,1,1)
+        class GCHello:
+            def __del__(self):
+                print("Destroyed from gc")
+
+        def gen():
+            yield
+
+        fd = open(__file__)
+        l = [fd, GCHello()]
+        l.append(l)
+        del fd
+        del l
+        gen()
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-11-11-01-56.gh-issue-95818.iClLdl.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-11-11-01-56.gh-issue-95818.iClLdl.rst
new file mode 100644 (file)
index 0000000..1e243f5
--- /dev/null
@@ -0,0 +1 @@
+Skip over incomplete frames in :c:func:`PyThreadState_GetFrame`.
index df56c0530f05b0b19ab1751707f36ad6d07455d9..2e4585688ea8c3095573b082b47682163359d4b0 100644 (file)
@@ -1255,10 +1255,14 @@ PyFrameObject*
 PyThreadState_GetFrame(PyThreadState *tstate)
 {
     assert(tstate != NULL);
-    if (tstate->cframe->current_frame == NULL) {
+    _PyInterpreterFrame *f = tstate->cframe->current_frame;
+    while (f && _PyFrame_IsIncomplete(f)) {
+        f = f->previous;
+    }
+    if (f == NULL) {
         return NULL;
     }
-    PyFrameObject *frame = _PyFrame_GetFrameObject(tstate->cframe->current_frame);
+    PyFrameObject *frame = _PyFrame_GetFrameObject(f);
     if (frame == NULL) {
         PyErr_Clear();
     }