self.assertIsInstance(res, dict)
self.assertEqual(list(res.items()), expected)
+ def test_frames_are_popped_after_failed_calls(self):
+ # GH-93252: stuff blows up if we don't pop the new frame after
+ # recovering from failed calls:
+ def f():
+ pass
+ for _ in range(1000):
+ try:
+ f(None)
+ except TypeError:
+ pass
+ # BOOM!
+
@cpython_only
class CFunctionCallsErrorMessages(unittest.TestCase):
}
if (initialize_locals(tstate, func, localsarray, args, argcount, kwnames)) {
assert(frame->owner != FRAME_OWNED_BY_GENERATOR);
- _PyFrame_Clear(frame);
+ _PyEvalFrameClearAndPop(tstate, frame);
return NULL;
}
return frame;
static void
_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
{
+ // Make sure that this is, indeed, the top frame. We can't check this in
+ // _PyThreadState_PopFrame, since f_code is already cleared at that point:
+ assert((PyObject **)frame + frame->f_code->co_framesize ==
+ tstate->datastack_top);
tstate->recursion_remaining--;
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
assert(frame->owner == FRAME_OWNED_BY_THREAD);