Skip to content

Assertion _tstate->jit_tracer_state.initial_state.func != NULL failed in _PyOptimizer_Optimize #143610

@devdanzin

Description

@devdanzin

Crash report

What happened?

It's possible to abort a patched JIT build by running the code below. The interpreter must be called from a venv in which lafleur is installed as editable, likely due to that priming the GC into a state suitable for the crash.

Necessary patch

diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h
index fadd11f04ec..3e779a141af 100644
--- a/Include/internal/pycore_backoff.h
+++ b/Include/internal/pycore_backoff.h
@@ -125,7 +125,7 @@ trigger_backoff_counter(void)
 // For example, 4095 does not work for the nqueens benchmark on pyperformance
 // as we always end up tracing the loop iteration's
 // exhaustion iteration. Which aborts our current tracer.
-#define JUMP_BACKWARD_INITIAL_VALUE 4000
+#define JUMP_BACKWARD_INITIAL_VALUE 63
 #define JUMP_BACKWARD_INITIAL_BACKOFF 6
 static inline _Py_BackoffCounter
 initial_jump_backoff_counter(_PyPolicy *policy)
@@ -139,7 +139,7 @@ initial_jump_backoff_counter(_PyPolicy *policy)
  * Must be larger than ADAPTIVE_COOLDOWN_VALUE,
  * otherwise when a side exit warms up we may construct
  * a new trace before the Tier 1 code has properly re-specialized. */
-#define SIDE_EXIT_INITIAL_VALUE 4000
+#define SIDE_EXIT_INITIAL_VALUE 63
 #define SIDE_EXIT_INITIAL_BACKOFF 6

 static inline _Py_BackoffCounter

To install lafleur as editable, first create a venv and activate it, then clone the lafleur repo and run pip install -e /path/to/lafleur/clone.

This MRE must be invoked like this:

/path/to/venv/with/editable/lafleur/install/bin/python mre.py
MRE

import email
from itertools import batched

f = 0.0
s = ""
i = 0
a: B

def f1():
    class P: 1

    for z in range(65): ...
    i + i
    i + i

    class A: ...

    class P:
        def _():
            if P: i

    i + 1
    f + f
    f + f

    class A:
        def _(): ...

    class C:
        def _():
            if C: i

    f + f
    c = f + f
    c = f + f
    s > s
    s > s
    s > s
    z * i
    z * i

    class a:
        def c(): i

        def _(): ...
        def __(): ...

    class A:
        def _():
            try:
                for _ in a: ...
            except: ...

    z * i
    1 * i
    z * i
    z ^ i
    i ^ i
    i ^ i
    1 ^ i
    1 ^ i
    i & 1
    i & i

    class z:
        def __init__(C, a):
            C.A = 0

        def __aiter__(C): return C

        async def __anext__(C):
            if C.A:
                raise StopAsyncIteration
            C.A = 1

    class A:
        def _(): 0

        async def A():
            for _ in range(5):
                async for _ in z(1): ...

        try:
            a = A()
            a.send(None)
        except: ...

    class A:
        a: ...

    class A:
        def _(): ...

for _ in range(300):
    f1()

Backtrace

python: Python/optimizer.c:144: int _PyOptimizer_Optimize(_PyInterpreterFrame *, PyThreadState *): Assertion `_tstate->jit_tracer_state.initial_state.func != NULL' failed.

Program received signal SIGABRT, Aborted.

#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=0) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (threadid=<optimized out>, signo=6) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:100
#3  0x00007ffff7c45e2e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7c28888 in __GI_abort () at ./stdlib/abort.c:77
#5  0x00007ffff7c287f0 in __assert_fail_base (fmt=<optimized out>, assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:118
#6  0x00007ffff7c3c19f in __assert_fail (assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:127
#7  0x00005555563e5f09 in _PyOptimizer_Optimize (frame=frame@entry=0x7e8ff6de5298, tstate=tstate@entry=0x555556ea42c0 <_PyRuntime+359392>) at Python/optimizer.c:144
#8  0x0000555555ed6364 in stop_tracing_and_jit (tstate=0x555556ea42c0 <_PyRuntime+359392>, frame=frame@entry=0x7e8ff6de5298) at Python/ceval.c:1464
#9  0x0000555555e94a95 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:11580
#10 0x0000555555e70c98 in _PyEval_EvalFrame (tstate=0x555556ea42c0 <_PyRuntime+359392>, frame=0x7e8ff6de5220, throwflag=0) at ./Include/internal/pycore_ceval.h:118
#11 _PyEval_Vector (tstate=<optimized out>, func=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:2542
#12 0x0000555555e706b5 in PyEval_EvalCode (co=<optimized out>, globals=<optimized out>, locals=0x7c7ff6e86440) at Python/ceval.c:1008
#13 0x000055555647ae3f in run_eval_code_obj (tstate=tstate@entry=0x555556ea42c0 <_PyRuntime+359392>, co=co@entry=0x7d2ff6e39290, globals=globals@entry=0x7c7ff6e86440,
    locals=locals@entry=0x7c7ff6e86440) at Python/pythonrun.c:1366
#14 0x000055555647a00c in run_mod (mod=<optimized out>, filename=<optimized out>, globals=<optimized out>, locals=<optimized out>, flags=<optimized out>, arena=<optimized out>,
    interactive_src=<optimized out>, generate_new_source=<optimized out>) at Python/pythonrun.c:1469
#15 0x000055555647460d in pyrun_file (fp=fp@entry=0x7d4ff6e03300, filename=filename@entry=0x7ccff6e2a6a0, start=start@entry=257, globals=globals@entry=0x7c7ff6e86440,
    locals=locals@entry=0x7c7ff6e86440, closeit=closeit@entry=1, flags=0x7bfff5c3df10) at Python/pythonrun.c:1294
#16 0x000055555647216d in _PyRun_SimpleFileObject (fp=<optimized out>, filename=<optimized out>, closeit=<optimized out>, flags=<optimized out>) at Python/pythonrun.c:518
#17 0x00005555564714de in _PyRun_AnyFileObject (fp=fp@entry=0x7d4ff6e03300, filename=filename@entry=0x7ccff6e2a6a0, closeit=closeit@entry=1, flags=flags@entry=0x7bfff5c3df10)
    at Python/pythonrun.c:81
#18 0x00005555564ed64b in pymain_run_file_obj (program_name=0x7caff6e80ae0, filename=0x7ccff6e2a6a0, skip_source_first_line=0) at Modules/main.c:410
#19 pymain_run_file (config=0x555556e6f398 <_PyRuntime+142520>) at Modules/main.c:429
#20 0x00005555564eb714 in pymain_run_python (exitcode=0x7bfff5c3db00) at Modules/main.c:691
#21 Py_RunMain () at Modules/main.c:772
#22 0x00005555564ec617 in pymain_main (args=<optimized out>) at Modules/main.c:802
#23 0x00005555564ec788 in Py_BytesMain (argc=<optimized out>, argv=0x7fffffffdb98) at Modules/main.c:826
#24 0x00007ffff7c2a575 in __libc_start_call_main (main=main@entry=0x55555591cc40 <main>, argc=argc@entry=2, argv=argv@entry=0x7fffffffdb98) at ../sysdeps/nptl/libc_start_call_main.h:58
#25 0x00007ffff7c2a628 in __libc_start_main_impl (main=0x55555591cc40 <main>, argc=2, argv=0x7fffffffdb98, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
    stack_end=0x7fffffffdb88) at ../csu/libc-start.c:360
#26 0x00005555558334f5 in _start ()

Output from running with PYTHON_LLTRACE=4 PYTHON_OPT_DEBUG=4:
093730_abort_lltrace_opt_debug.txt

Found using lafleur.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.15.0a3+ (heads/main-dirty:6d54b6ac7d5, Jan 9 2026, 11:35:46) [Clang 21.1.2 (2ubuntu6)]

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions