Skip to content

Commit 36a3372

Browse files
tiranbrandtbucher
andauthored
[3.11] gh-94215: Fix error handling for line-tracing events (GH-94681) (GH-94688)
* Re-enable crasher * Fix error handling for line-tracing events * blurb add (cherry picked from commit 23ee4a8) Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
1 parent 73a1800 commit 36a3372

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

Lib/test/test_pdb.py

-1
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,6 @@ def test_issue42383(self):
20852085
expected = '(Pdb) The correct file was executed'
20862086
self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected)
20872087

2088-
@unittest.skip("test crashes, see gh-94215")
20892088
def test_gh_94215_crash(self):
20902089
script = """\
20912090
def func():
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix an issue where exceptions raised by line-tracing events would cause
2+
frames to be left in an invalid state, possibly resulting in a hard crash of
3+
the interpreter.

Python/ceval.c

+14-5
Original file line numberDiff line numberDiff line change
@@ -5642,16 +5642,25 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
56425642
err = maybe_call_line_trace(tstate->c_tracefunc,
56435643
tstate->c_traceobj,
56445644
tstate, frame, instr_prev);
5645+
// Reload possibly changed frame fields:
5646+
stack_pointer = _PyFrame_GetStackPointer(frame);
5647+
frame->stacktop = -1;
5648+
// next_instr is only reloaded if tracing *does not* raise.
5649+
// This is consistent with the behavior of older Python
5650+
// versions. If a trace function sets a new f_lineno and
5651+
// *then* raises, we use the *old* location when searching
5652+
// for an exception handler, displaying the traceback, and
5653+
// so on:
56455654
if (err) {
5646-
/* trace function raised an exception */
5655+
// next_instr wasn't incremented at the start of this
5656+
// instruction. Increment it before handling the error,
5657+
// so that it looks the same as a "normal" instruction:
56475658
next_instr++;
56485659
goto error;
56495660
}
5650-
/* Reload possibly changed frame fields */
5661+
// Reload next_instr. Don't increment it, though, since
5662+
// we're going to re-dispatch to the "true" instruction now:
56515663
next_instr = frame->prev_instr;
5652-
5653-
stack_pointer = _PyFrame_GetStackPointer(frame);
5654-
frame->stacktop = -1;
56555664
}
56565665
}
56575666
}

0 commit comments

Comments
 (0)