Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8a285df

Browse files
authored
GH-93252: Fix error handling for failed Python calls (GH-94693)
1 parent4bed0db commit8a285df

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

‎Lib/test/test_call.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ def fn(**kw):
2626
self.assertIsInstance(res,dict)
2727
self.assertEqual(list(res.items()),expected)
2828

29+
deftest_frames_are_popped_after_failed_calls(self):
30+
# GH-93252: stuff blows up if we don't pop the new frame after
31+
# recovering from failed calls:
32+
deff():
33+
pass
34+
for_inrange(1000):
35+
try:
36+
f(None)
37+
exceptTypeError:
38+
pass
39+
# BOOM!
40+
2941

3042
@cpython_only
3143
classCFunctionCallsErrorMessages(unittest.TestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an issue that caused internal frames to outlive failed Python function
2+
calls, possibly resulting in memory leaks or hard interpreter crashes.

‎Python/ceval.c‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6410,7 +6410,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
64106410
}
64116411
if (initialize_locals(tstate,func,localsarray,args,argcount,kwnames)) {
64126412
assert(frame->owner!=FRAME_OWNED_BY_GENERATOR);
6413-
_PyFrame_Clear(frame);
6413+
_PyEvalFrameClearAndPop(tstate,frame);
64146414
returnNULL;
64156415
}
64166416
returnframe;
@@ -6432,6 +6432,10 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
64326432
staticvoid
64336433
_PyEvalFrameClearAndPop(PyThreadState*tstate,_PyInterpreterFrame*frame)
64346434
{
6435+
// Make sure that this is, indeed, the top frame. We can't check this in
6436+
// _PyThreadState_PopFrame, since f_code is already cleared at that point:
6437+
assert((PyObject**)frame+frame->f_code->co_framesize==
6438+
tstate->datastack_top);
64356439
tstate->recursion_remaining--;
64366440
assert(frame->frame_obj==NULL||frame->frame_obj->f_frame==frame);
64376441
assert(frame->owner==FRAME_OWNED_BY_THREAD);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp