]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-140936: Fix JIT assertion crash at finalization if some generator is alive...
authorMikhail Efimov <efimov.mikhail@gmail.com>
Thu, 13 Nov 2025 16:11:57 +0000 (19:11 +0300)
committerGitHub <noreply@github.com>
Thu, 13 Nov 2025 16:11:57 +0000 (16:11 +0000)
gh-140936: Fix JIT assertion crash at finalization if some generator is alive (GH-140969)

Lib/test/test_capi/test_opt.py
Python/optimizer.c

index c74c8ee0eef8e292ed45fc760a2b5f05b165477a..1860325cba616d2640ea786f3ed0c1b1c79cfaea 100644 (file)
@@ -1972,6 +1972,26 @@ class TestUopsOptimization(unittest.TestCase):
         assert ex is not None
         """))
 
+    def test_interpreter_finalization_with_generator_alive(self):
+        script_helper.assert_python_ok("-c", textwrap.dedent("""
+            import sys
+            t = tuple(range(%d))
+            def simple_for():
+                for x in t:
+                    x
+
+            def gen():
+                try:
+                    yield
+                except:
+                    simple_for()
+
+            sys.settrace(lambda *args: None)
+            simple_for()
+            g = gen()
+            next(g)
+        """ % _testinternalcapi.SPECIALIZATION_THRESHOLD))
+
 
 def global_identity(x):
     return x
index e2b6adfab595f20b78b33f1687d2f83c1eb6b7c2..6679eecd648a85ca95d34363dc30e506bfa6308a 100644 (file)
@@ -116,7 +116,14 @@ _PyOptimizer_Optimize(
     _PyExecutorObject **executor_ptr, int chain_depth)
 {
     _PyStackRef *stack_pointer = frame->stackpointer;
-    assert(_PyInterpreterState_GET()->jit);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    if (!interp->jit) {
+        // gh-140936: It is possible that interp->jit will become false during
+        // interpreter finalization. However, the specialized JUMP_BACKWARD_JIT
+        // instruction may still be present. In this case, we should
+        // return immediately without optimization.
+        return 0;
+    }
     // The first executor in a chain and the MAX_CHAIN_DEPTH'th executor *must*
     // make progress in order to avoid infinite loops or excessively-long
     // side-exit chains. We can only insert the executor into the bytecode if