Skip to content

Commit 78c2545

Browse files
authored
gh-113939: Frame clear, clear locals (#113940)
1 parent b905fad commit 78c2545

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

Lib/test/test_frame.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,28 @@ class C:
5555
# The reference was released by .clear()
5656
self.assertIs(None, wr())
5757

58+
def test_clear_locals_after_f_locals_access(self):
59+
# see gh-113939
60+
class C:
61+
pass
62+
63+
wr = None
64+
def inner():
65+
nonlocal wr
66+
c = C()
67+
wr = weakref.ref(c)
68+
1/0
69+
70+
try:
71+
inner()
72+
except ZeroDivisionError as exc:
73+
support.gc_collect()
74+
self.assertIsNotNone(wr())
75+
print(exc.__traceback__.tb_next.tb_frame.f_locals)
76+
exc.__traceback__.tb_next.tb_frame.clear()
77+
support.gc_collect()
78+
self.assertIsNone(wr())
79+
5880
def test_clear_does_not_clear_specials(self):
5981
class C:
6082
pass
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
frame.clear():
2+
Clear frame.f_locals as well, and not only the fast locals.
3+
This is relevant once frame.f_locals was accessed,
4+
which would contain also references to all the locals.

Objects/frameobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,7 @@ frame_tp_clear(PyFrameObject *f)
926926
Py_CLEAR(locals[i]);
927927
}
928928
f->f_frame->stacktop = 0;
929+
Py_CLEAR(f->f_frame->f_locals);
929930
return 0;
930931
}
931932

0 commit comments

Comments
 (0)