Skip to content

Commit 9cc800a

Browse files
committed
pythongh-79932: do not allow to clear a suspended frame
1 parent b27b57c commit 9cc800a

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

Lib/test/test_frame.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import re
33
import sys
44
import textwrap
5+
import traceback
56
import types
67
import unittest
78
import weakref
@@ -111,6 +112,25 @@ def g():
111112
f.clear()
112113
self.assertTrue(endly)
113114

115+
def test_clear_suspended_generator(self):
116+
# Attempting to clear a suspended generator frame is forbidden.
117+
def g():
118+
for i in range(5):
119+
try:
120+
1/0
121+
except ZeroDivisionError as e:
122+
yield (e, i)
123+
124+
gen = g()
125+
res = []
126+
for e, i in gen:
127+
res.append(i)
128+
with self.assertRaises(RuntimeError):
129+
f = e.__traceback__.tb_frame
130+
self.assertIsNotNone(f)
131+
f.clear()
132+
self.assertEqual(res, list(range(5)))
133+
114134
def test_lineno_with_tracing(self):
115135
def record_line():
116136
f = sys._getframe(1)

Objects/frameobject.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,8 @@ frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
949949
{
950950
if (f->f_frame->owner == FRAME_OWNED_BY_GENERATOR) {
951951
PyGenObject *gen = _PyFrame_GetGenerator(f->f_frame);
952-
if (gen->gi_frame_state == FRAME_EXECUTING) {
952+
if (gen->gi_frame_state == FRAME_EXECUTING ||
953+
gen->gi_frame_state == FRAME_SUSPENDED) {
953954
goto running;
954955
}
955956
_PyGen_Finalize((PyObject *)gen);

0 commit comments

Comments
 (0)