gh-94215: Fix error handling for line-tracing events (GH-94681)

* Re-enable crasher
* Fix error handling for line-tracing events
* blurb add
This commit is contained in:
Brandt Bucher 2022-07-08 05:40:35 -07:00 committed by GitHub
parent e5b841a403
commit 23ee4a8067
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 6 deletions

View file

@ -2085,7 +2085,6 @@ def bœr():
expected = '(Pdb) The correct file was executed' expected = '(Pdb) The correct file was executed'
self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected) self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected)
@unittest.skip("test crashes, see gh-94215")
def test_gh_94215_crash(self): def test_gh_94215_crash(self):
script = """\ script = """\
def func(): def func():

View file

@ -0,0 +1,3 @@
Fix an issue where exceptions raised by line-tracing events would cause
frames to be left in an invalid state, possibly resulting in a hard crash of
the interpreter.

View file

@ -5683,16 +5683,25 @@ handle_eval_breaker:
err = maybe_call_line_trace(tstate->c_tracefunc, err = maybe_call_line_trace(tstate->c_tracefunc,
tstate->c_traceobj, tstate->c_traceobj,
tstate, frame, instr_prev); tstate, frame, instr_prev);
// Reload possibly changed frame fields:
stack_pointer = _PyFrame_GetStackPointer(frame);
frame->stacktop = -1;
// next_instr is only reloaded if tracing *does not* raise.
// This is consistent with the behavior of older Python
// versions. If a trace function sets a new f_lineno and
// *then* raises, we use the *old* location when searching
// for an exception handler, displaying the traceback, and
// so on:
if (err) { if (err) {
/* trace function raised an exception */ // next_instr wasn't incremented at the start of this
// instruction. Increment it before handling the error,
// so that it looks the same as a "normal" instruction:
next_instr++; next_instr++;
goto error; goto error;
} }
/* Reload possibly changed frame fields */ // Reload next_instr. Don't increment it, though, since
// we're going to re-dispatch to the "true" instruction now:
next_instr = frame->prev_instr; next_instr = frame->prev_instr;
stack_pointer = _PyFrame_GetStackPointer(frame);
frame->stacktop = -1;
} }
} }
} }