python / python/cpython

JIT: Assertion `size < MAX_EXECUTORS_SIZE` failed in `get_index_for_executor`

Open
#143,807 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

interpreter-core topic-JIT type-crash
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Crash report

What happened?

It's possible to cause an abort in a patched JIT build by running the code below. This bug doesn't seem to repro if using an interpreter from a venv with lots o stuff installed, but it does when directly calling Python from a build dir: /path/to/build/python mre.py.

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
MRE

from sys import stderr
import gc
gc.set_threshold(1)
import random

# u/U means an undefined name
def f1():
    def v(a=2): ...

    try: res = v()
    except Exception: u()
    except U: u

    class A:
        def _(self): ...

    d = {}
    for i in range(10):
        try: u
        except Exception: pass
        def _(): ...

    class B:
        def _(self): b = 1

    class C(B):
        def f(self):
            for i in [4**62]:
                C._(object)

    for i in (-1, 0):
        c = C()
    for _ in range(299):
        try: _ = c.f()
        except Exception: u

    for i in range(76):
        C.__bases__ = (object,)
    for _ in range(100):
        try: _ = c.f()
        except AttributeError: pass

    for i in range(501):
        if i - 9 == 3: u
        elif u / 9 == 2: (var,) = {}
        elif u / 1 != 3:
            for i in [24]: 1 / 0
        try: u(u)
        except U: u

    for i in []:
        class D: u
    t = 2, 0
    (u,)

for i in range(300):
    try: f1()
    except Exception as e: print(i, file=stderr)

Backtrace

python: Python/optimizer.c:71: int32_t get_index_for_executor(PyCodeObject *, _Py_CODEUNIT *): Assertion `size < MAX_EXECUTORS_SIZE' 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  0x00005555563ff51e in get_index_for_executor (code=0x7d9ff6dfaa90, instr=0x7d9ff6dfaed2) at Python/optimizer.c:71
#8  _PyOptimizer_Optimize (frame=frame@entry=0x7e8ff6de52b0, tstate=tstate@entry=0x555556ed3030 <_PyRuntime+359408>) at Python/optimizer.c:177
#9  0x0000555555eda0a4 in stop_tracing_and_jit (tstate=0x555556ed3030 <_PyRuntime+359408>, frame=frame@entry=0x7e8ff6de52b0) at Python/ceval.c:1461
#10 0x0000555555e9693a in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:11868
#11 0x0000555555e72e68 in _PyEval_EvalFrame (tstate=0x555556ed3030 <_PyRuntime+359408>, frame=0x7e8ff6de5220, throwflag=0) at ./Include/internal/pycore_ceval.h:118
#12 _PyEval_Vector (tstate=<optimized out>, func=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:2541
#13 0x0000555555e72885 in PyEval_EvalCode (co=<optimized out>, globals=<optimized out>, locals=0x7c7ff6e863c0) at Python/ceval.c:1005
#14 0x000055555649d01f in run_eval_code_obj (tstate=tstate@entry=0x555556ed3030 <_PyRuntime+359408>, co=co@entry=0x7d3ff6e16050, globals=globals@entry=0x7c7ff6e863c0,
    locals=locals@entry=0x7c7ff6e863c0) at Python/pythonrun.c:1366
#15 0x000055555649c1ec 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
#16 0x00005555564967ed in pyrun_file (fp=fp@entry=0x7d4ff6defa80, filename=filename@entry=0x7ccff6dfaef0, start=start@entry=257, globals=globals@entry=0x7c7ff6e863c0,
    locals=locals@entry=0x7c7ff6e863c0, closeit=closeit@entry=1, flags=0x7bfff5c1e910) at Python/pythonrun.c:1294
#17 0x000055555649434d in _PyRun_SimpleFileObject (fp=<optimized out>, filename=<optimized out>, closeit=<optimized out>, flags=<optimized out>) at Python/pythonrun.c:518
#18 0x00005555564936be in _PyRun_AnyFileObject (fp=fp@entry=0x7d4ff6defa80, filename=filename@entry=0x7ccff6dfaef0, closeit=closeit@entry=1, flags=flags@entry=0x7bfff5c1e910)
    at Python/pythonrun.c:81
#19 0x000055555650ff2b in pymain_run_file_obj (program_name=0x7caff6e230d0, filename=0x7ccff6dfaef0, skip_source_first_line=0) at Modules/main.c:410
#20 pymain_run_file (config=0x555556e9e0f8 <_PyRuntime+142520>) at Modules/main.c:429
#21 0x000055555650dff4 in pymain_run_python (exitcode=0x7bfff5c1e500) at Modules/main.c:691
#22 Py_RunMain () at Modules/main.c:772
#23 0x000055555650eef7 in pymain_main (args=<optimized out>) at Modules/main.c:802
#24 0x000055555650f068 in Py_BytesMain (argc=<optimized out>, argv=0x7fffffffdbb8) at Modules/main.c:826
#25 0x00007ffff7c2a575 in __libc_start_call_main (main=main@entry=0x55555591ec40 <main>, argc=argc@entry=2, argv=argv@entry=0x7fffffffdbb8) at ../sysdeps/nptl/libc_start_call_main.h:58
#26 0x00007ffff7c2a628 in __libc_start_main_impl (main=0x55555591ec40 <main>, argc=2, argv=0x7fffffffdbb8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
    stack_end=0x7fffffffdba8) at ../csu/libc-start.c:360
#27 0x00005555558354f5 in _start ()

Output from running with PYTHON_LLTRACE=4 PYTHON_OPT_DEBUG=4:
3495_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:fca7fec88ce, Jan 13 2026, 13:04:59) [Clang 21.1.2 (2ubuntu6)]

Linked PRs
  • gh-143812
  • gh-143814

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in Python/optimizer.c at get_index_for_executor and review the backtrace, then inspect Include/internal/pycore_backoff.h and the supplied MRE. Run the patched CPython main build with the reproducer and confirm it no longer aborts on the MAX_EXECUTORS_SIZE assertion.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.