From 36a3372d5105ffbd083a56cc8442a81a5bfeb19b Mon Sep 17 00:00:00 2001 From: Christian Heimes <christian@python.org> Date: Fri, 8 Jul 2022 15:25:53 +0200 Subject: [PATCH] [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 23ee4a8067506e6c9c47748185653617413f7a60) Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com> --- Lib/test/test_pdb.py | 1 - ...2-07-07-21-13-25.gh-issue-94215._Sv9Ms.rst | 3 +++ Python/ceval.c | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-07-07-21-13-25.gh-issue-94215._Sv9Ms.rst diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 968a32fce47..55c3283e26b 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -2085,7 +2085,6 @@ def test_issue42383(self): expected = '(Pdb) The correct file was executed' self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected) - @unittest.skip("test crashes, see gh-94215") def test_gh_94215_crash(self): script = """\ def func(): diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-07-21-13-25.gh-issue-94215._Sv9Ms.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-07-21-13-25.gh-issue-94215._Sv9Ms.rst new file mode 100644 index 00000000000..07af472fbdc --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-07-21-13-25.gh-issue-94215._Sv9Ms.rst @@ -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. diff --git a/Python/ceval.c b/Python/ceval.c index 32f471f574b..1a545457051 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5642,16 +5642,25 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int err = maybe_call_line_trace(tstate->c_tracefunc, tstate->c_traceobj, 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) { - /* 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++; 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; - - stack_pointer = _PyFrame_GetStackPointer(frame); - frame->stacktop = -1; } } } -- GitLab