File tree
Include/internal
Lib/test
Misc/NEWS.d/next/Core and Builtins
Objects
Python
Original file line numberDiff line numberDiff line change@@ -227,6 +227,9 @@ _PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
227227return_PyFrame_MakeAndSetFrameObject(frame);
228228}
229229230+void
231+_PyFrame_ClearLocals(_PyInterpreterFrame*frame);
232+230233/* Clears all references in the frame.
231234 * If take is non-zero, then the _PyInterpreterFrame frame
232235 * may be transferred to the frame object it references
Original file line numberDiff line numberDiff line change@@ -532,6 +532,26 @@ def f():
532532withself.assertRaises(RuntimeError):
533533gen.close()
534534535+deftest_close_releases_frame_locals(self):
536+# See gh-118272
537+538+classFoo:
539+pass
540+541+f=Foo()
542+f_wr=weakref.ref(f)
543+544+defgenfn():
545+a=f
546+yield
547+548+g=genfn()
549+next(g)
550+delf
551+g.close()
552+support.gc_collect()
553+self.assertIsNone(f_wr())
554+535555536556classGeneratorThrowTest(unittest.TestCase):
537557Original file line numberDiff line numberDiff line change@@ -0,0 +1,2 @@
1+Fix bug where ``generator.close`` does not free the generator frame's
2+locals.
Original file line numberDiff line numberDiff line change@@ -380,6 +380,7 @@ gen_close(PyGenObject *gen, PyObject *args)
380380// RESUME after YIELD_VALUE and exception depth is 1
381381assert((oparg&RESUME_OPARG_LOCATION_MASK) !=RESUME_AT_FUNC_START);
382382gen->gi_frame_state=FRAME_COMPLETED;
383+_PyFrame_ClearLocals((_PyInterpreterFrame*)gen->gi_iframe);
383384Py_RETURN_NONE;
384385 }
385386 }
Original file line numberDiff line numberDiff line change@@ -94,6 +94,17 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
9494 }
9595}
969697+void
98+_PyFrame_ClearLocals(_PyInterpreterFrame*frame)
99+{
100+assert(frame->stacktop >= 0);
101+for (inti=0; i<frame->stacktop; i++) {
102+Py_XDECREF(frame->localsplus[i]);
103+ }
104+frame->stacktop=0;
105+Py_CLEAR(frame->f_locals);
106+}
107+97108void
98109_PyFrame_ClearExceptCode(_PyInterpreterFrame*frame)
99110{
@@ -114,11 +125,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
114125 }
115126Py_DECREF(f);
116127 }
117-assert(frame->stacktop >= 0);
118-for (inti=0; i<frame->stacktop; i++) {
119-Py_XDECREF(frame->localsplus[i]);
120- }
121-Py_XDECREF(frame->f_locals);
128+_PyFrame_ClearLocals(frame);
122129Py_DECREF(frame->f_funcobj);
123130}
124131