]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-94215: Fix error handling for line-tracing events (GH-94681)
authorBrandt Bucher <brandtbucher@microsoft.com>
Fri, 8 Jul 2022 12:40:35 +0000 (05:40 -0700)
committerGitHub <noreply@github.com>
Fri, 8 Jul 2022 12:40:35 +0000 (14:40 +0200)
* Re-enable crasher
* Fix error handling for line-tracing events
* blurb add

Lib/test/test_pdb.py
Misc/NEWS.d/next/Core and Builtins/2022-07-07-21-13-25.gh-issue-94215._Sv9Ms.rst [new file with mode: 0644]
Python/ceval.c

index 968a32fce47b69d902f6d0e06670f5b8ca111c9e..55c3283e26b1e97d7a280470710c0f8a12eddf09 100644 (file)
@@ -2085,7 +2085,6 @@ def bœr():
             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 (file)
index 0000000..07af472
--- /dev/null
@@ -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.
index cdb14d84c0670d99f1b9d3674cc08da4e240ad09..0176002432e8ddff3462421f0ac91114e53fe462 100644 (file)
@@ -5683,16 +5683,25 @@ handle_eval_breaker:
                     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;
                 }
             }
         }