Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d7bfddf

Browse files
committed
Add _PyFrame_ClearExceptCodeAndFunction
1 parent 1fddb7f commit d7bfddf

5 files changed

Lines changed: 29 additions & 6 deletions

File tree

Include/internal/pycore_interpframe.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
368368
PyAPI_FUNC(void)
369369
_PyFrame_ClearExceptCode(_PyInterpreterFrame * frame);
370370

371+
void
372+
_PyFrame_ClearExceptCodeAndFunction(_PyInterpreterFrame *frame);
373+
371374
int
372375
_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg);
373376

InternalDocs/generators.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ the generator object.
5353
When a generator object is destroyed in [`gen_dealloc`](../Objects/genobject.c),
5454
its embedded `_PyInterpreterFrame` field may need to be preserved, if it is exposed
5555
to Python as part of a [`PyFrameObject`](frames.md#frame-objects). This is detected
56-
in [`_PyFrame_ClearExceptCode`](../Python/frame.c) by the fact that the interpreter
56+
in [`_PyFrame_ClearExceptCodeAndFunction`](../Python/frame.c) by the fact that the interpreter
5757
frame's `frame_obj` field is set, and the frame object it points to has refcount
5858
greater than 1. If so, the `take_ownership()` function is called to create a new
5959
copy of the interpreter frame and transfer ownership of it from the generator to

Objects/genobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ gen_clear_frame(PyGenObject *gen)
170170
_PyInterpreterFrame *frame = &gen->gi_iframe;
171171
_PyThreadState_UpdateLastProfiledFrame(_PyThreadState_GET(), frame, frame->previous);
172172
frame->previous = NULL;
173-
_PyFrame_ClearExceptCode(frame);
173+
_PyFrame_ClearExceptCodeAndFunction(frame);
174174
_PyErr_ClearExcState(&gen->gi_exc_state);
175175
}
176176

Python/ceval.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,10 +1998,7 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
19981998
gen->gi_exc_state.previous_item = NULL;
19991999
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
20002000
frame->previous = NULL;
2001-
if (PyGen_Check(gen)) {
2002-
frame->f_funcobj = PyStackRef_DUP(frame->f_funcobj);
2003-
}
2004-
_PyFrame_ClearExceptCode(frame);
2001+
_PyFrame_ClearExceptCodeAndFunction(frame);
20052002
_PyErr_ClearExcState(&gen->gi_exc_state);
20062003
// gh-143939: There must not be any escaping calls between setting
20072004
// the generator return kind and returning from _PyEval_EvalFrame.

Python/frame.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,29 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
123123
PyStackRef_CLEAR(frame->f_funcobj);
124124
}
125125

126+
void
127+
_PyFrame_ClearExceptCodeAndFunction(_PyInterpreterFrame *frame)
128+
{
129+
/* It is the responsibility of the owning generator/coroutine
130+
* to have cleared the enclosing generator, if any. */
131+
assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||
132+
FT_ATOMIC_LOAD_INT8_RELAXED(_PyGen_GetGeneratorFromFrame(frame)->gi_frame_state) == FRAME_CLEARED);
133+
// GH-99729: Clearing this frame can expose the stack (via finalizers). It's
134+
// crucial that this frame has been unlinked, and is no longer visible:
135+
assert(_PyThreadState_GET()->current_frame != frame);
136+
if (frame->frame_obj) {
137+
PyFrameObject *f = frame->frame_obj;
138+
frame->frame_obj = NULL;
139+
if (!_PyObject_IsUniquelyReferenced((PyObject *)f)) {
140+
take_ownership(f, frame);
141+
Py_DECREF(f);
142+
return;
143+
}
144+
Py_DECREF(f);
145+
}
146+
_PyFrame_ClearLocals(frame);
147+
}
148+
126149
/* Unstable API functions */
127150

128151
PyObject *

0 commit comments

Comments
 (0)