Skip to content

Commit 1b46d11

Browse files
authored
GH-95818: Skip incomplete frames in PyThreadState_GetFrame (GH-95886)
1 parent 23a757f commit 1b46d11

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

Lib/test/test_frame.py

+22
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,28 @@ def inner():
235235
r"^<frame at 0x[0-9a-fA-F]+, file %s, line %d, code inner>$"
236236
% (file_repr, offset + 5))
237237

238+
class TestIncompleteFrameAreInvisible(unittest.TestCase):
239+
240+
def test_issue95818(self):
241+
#See GH-95818 for details
242+
import gc
243+
self.addCleanup(gc.set_threshold, *gc.get_threshold())
244+
245+
gc.set_threshold(1,1,1)
246+
class GCHello:
247+
def __del__(self):
248+
print("Destroyed from gc")
249+
250+
def gen():
251+
yield
252+
253+
fd = open(__file__)
254+
l = [fd, GCHello()]
255+
l.append(l)
256+
del fd
257+
del l
258+
gen()
259+
238260

239261
if __name__ == "__main__":
240262
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Skip over incomplete frames in :c:func:`PyThreadState_GetFrame`.

Python/pystate.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -1255,10 +1255,14 @@ PyFrameObject*
12551255
PyThreadState_GetFrame(PyThreadState *tstate)
12561256
{
12571257
assert(tstate != NULL);
1258-
if (tstate->cframe->current_frame == NULL) {
1258+
_PyInterpreterFrame *f = tstate->cframe->current_frame;
1259+
while (f && _PyFrame_IsIncomplete(f)) {
1260+
f = f->previous;
1261+
}
1262+
if (f == NULL) {
12591263
return NULL;
12601264
}
1261-
PyFrameObject *frame = _PyFrame_GetFrameObject(tstate->cframe->current_frame);
1265+
PyFrameObject *frame = _PyFrame_GetFrameObject(f);
12621266
if (frame == NULL) {
12631267
PyErr_Clear();
12641268
}

0 commit comments

Comments
 (0)