Skip to content

Commit 23ee4a8

Browse files
authored
gh-94215: Fix error handling for line-tracing events (GH-94681)
* Re-enable crasher * Fix error handling for line-tracing events * blurb add
1 parent e5b841a commit 23ee4a8

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

Lib/test/test_pdb.py

Lines changed: 0 additions & 1 deletion
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():
Lines changed: 3 additions & 0 deletions
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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5683,16 +5683,25 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
56835683
err = maybe_call_line_trace(tstate->c_tracefunc,
56845684
tstate->c_traceobj,
56855685
tstate, frame, instr_prev);
5686+
// Reload possibly changed frame fields:
5687+
stack_pointer = _PyFrame_GetStackPointer(frame);
5688+
frame->stacktop = -1;
5689+
// next_instr is only reloaded if tracing *does not* raise.
5690+
// This is consistent with the behavior of older Python
5691+
// versions. If a trace function sets a new f_lineno and
5692+
// *then* raises, we use the *old* location when searching
5693+
// for an exception handler, displaying the traceback, and
5694+
// so on:
56865695
if (err) {
5687-
/* trace function raised an exception */
5696+
// next_instr wasn't incremented at the start of this
5697+
// instruction. Increment it before handling the error,
5698+
// so that it looks the same as a "normal" instruction:
56885699
next_instr++;
56895700
goto error;
56905701
}
5691-
/* Reload possibly changed frame fields */
5702+
// Reload next_instr. Don't increment it, though, since
5703+
// we're going to re-dispatch to the "true" instruction now:
56925704
next_instr = frame->prev_instr;
5693-
5694-
stack_pointer = _PyFrame_GetStackPointer(frame);
5695-
frame->stacktop = -1;
56965705
}
56975706
}
56985707
}

0 commit comments

Comments
 (0)