bpo-45813: Make sure that frame->generator is NULLed when generator is deallocated. (GH-29700)

This commit is contained in:
Mark Shannon 2021-11-22 14:01:23 +00:00 committed by GitHub
parent d9cedabeba
commit 7fd92a8b7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 12 additions and 0 deletions

View file

@ -2191,6 +2191,13 @@ class CoroutineTest(unittest.TestCase):
return 'end' return 'end'
self.assertEqual(run_async(run_gen()), ([], 'end')) self.assertEqual(run_async(run_gen()), ([], 'end'))
def test_bpo_45813(self):
'This would crash the interpreter in 3.11a2'
async def f():
pass
frame = f().cr_frame
frame.clear()
class CoroAsyncIOCompatTest(unittest.TestCase): class CoroAsyncIOCompatTest(unittest.TestCase):

View file

@ -0,0 +1 @@
Fix crash when calling coro.cr_frame.clear() after coroutine has been freed.

View file

@ -134,6 +134,7 @@ gen_dealloc(PyGenObject *gen)
InterpreterFrame *frame = gen->gi_xframe; InterpreterFrame *frame = gen->gi_xframe;
if (frame != NULL) { if (frame != NULL) {
gen->gi_xframe = NULL; gen->gi_xframe = NULL;
frame->generator = NULL;
frame->previous = NULL; frame->previous = NULL;
_PyFrame_Clear(frame, 1); _PyFrame_Clear(frame, 1);
} }

View file

@ -99,6 +99,9 @@ take_ownership(PyFrameObject *f, InterpreterFrame *frame)
int int
_PyFrame_Clear(InterpreterFrame * frame, int take) _PyFrame_Clear(InterpreterFrame * frame, int take)
{ {
/* It is the responsibility of the owning generator/coroutine
* to have cleared the generator pointer */
assert(frame->generator == NULL);
if (frame->frame_obj) { if (frame->frame_obj) {
PyFrameObject *f = frame->frame_obj; PyFrameObject *f = frame->frame_obj;
frame->frame_obj = NULL; frame->frame_obj = NULL;