python / python/cpython

JIT: `executor->vm_data.valid` assertion failure in `unlink_executor`

Ouverte
#136,996 15 commentaires 0 réactions 1 personne assignée Voir sur GitHub

@Fidget-Spinner y travaille déjà.

Depuis le 22/7/2025.

3.14 interpreter-core topic-JIT type-crash
Langage dominant
Python
Étoiles
77.2k
Forks
35.9k
Métriques de merge des PR
Métriques de PR en attente

Description

Crash report

What happened?

Sorry about the messy and convoluted bug report, I hope something interesting might be gleaned from it.

It's possible to non-deterministically abort a special debug JIT build by running the code below, running from a Python executable from a venv where you installed a package in editable mode. This darn requirement for an install in editable mode stumped me for hours!

For this special build, apply this diff (couldn't get it to work in a normal build by changing loop lengths):

index 454c8dde031..9e21c41421a 100644
--- a/Include/internal/pycore_backoff.h
+++ b/Include/internal/pycore_backoff.h
@@ -99,8 +99,8 @@ backoff_counter_triggers(_Py_BackoffCounter counter)
 // Must be larger than ADAPTIVE_COOLDOWN_VALUE, otherwise when JIT code is
 // invalidated we may construct a new trace before the bytecode has properly
 // re-specialized:
-#define JUMP_BACKWARD_INITIAL_VALUE 4095
-#define JUMP_BACKWARD_INITIAL_BACKOFF 12
+#define JUMP_BACKWARD_INITIAL_VALUE 63
+#define JUMP_BACKWARD_INITIAL_BACKOFF 6
 static inline _Py_BackoffCounter
 initial_jump_backoff_counter(void)
 {
@@ -112,8 +112,8 @@ initial_jump_backoff_counter(void)
  * 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 4095
-#define SIDE_EXIT_INITIAL_BACKOFF 12
+#define SIDE_EXIT_INITIAL_VALUE 63
+#define SIDE_EXIT_INITIAL_BACKOFF 6

 static inline _Py_BackoffCounter
 initial_temperature_backoff_counter(void)

This MRE must be invoked like this:

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

Sorry about the long MRE, this code seems stubbornly hard to reduce. MRE:

from random import random

class C_object_v1:

    def __getitem__(self, item):
        return 5
object_v1 = C_object_v1()


int_v4 = -51452741571812374
float_v6 = 46.1
float_v7 = 77.26

class StatefulLen_stateful_len_object_v12:
    def __init__(self):
        self.len_count = 0

    def __len__(self):
        _len = 0 if self.len_count < 70 else 99
        self.len_count += 1
        return _len
stateful_len_object_v12 = StatefulLen_stateful_len_object_v12()

def uop_harness_f1():
    class StatefulIter_uop_harness_f1_6059:

        def __init__(self):
            self._iter_count = 0
            self._iterable = {1, 2, 3}

        def __iter__(self):
            self._iter_count += 1
            if self._iter_count <= 67:
                return iter((None,))
            return iter(self._iterable)
    uop_harness_f1_6059 = StatefulIter_uop_harness_f1_6059()
    evil_iterable = StatefulIter_uop_harness_f1_6059()
    for _ in range(100):
        tuple(evil_iterable)
    object_v1 = globals()['object_v1']

    class SwappedClass_2950:
        pass
    object_v1.__class__ = SwappedClass_2950
    if object_v1:
        pass
    for i_loop_9595 in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 50:
        res_compareopint = int_v4 > int_v4
    if random() < 0.01:
        object_v1.__class__.get_value = lambda *a, **kw: 'patched!'
for i_f1 in range(500):
    try:
        uop_harness_f1()
    except Exception:
        break

Backtrace:

python: Python/optimizer.c:1436: unlink_executor: Assertion `executor->vm_data.valid' failed.

Program received signal SIGABRT, Aborted.
Download failed: Invalid argument.  Continuing without source file ./nptl/./nptl/pthread_kill.c.
__pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=0)
    at ./nptl/pthread_kill.c:44
warning: 44     ./nptl/pthread_kill.c: No such file or directory
(gdb) bt
#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  0x00007ffff7c4579e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7c288cd in __GI_abort () at ./stdlib/abort.c:73
#5  0x00007ffff7c28830 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  0x00007ffff7c3be1f in __assert_fail (assertion=<optimized out>, file=<optimized out>,
    line=<optimized out>, function=<optimized out>) at ./assert/assert.c:127
#7  0x00005555558a2603 in unlink_executor (executor=executor@entry=0x555555f44480)
    at Python/optimizer.c:1436
#8  0x00005555558a31a7 in uop_dealloc (op=op@entry=0x555555f44480) at Python/optimizer.c:271
#9  0x00005555556dc978 in _Py_Dealloc (op=0x555555f44480) at Objects/object.c:3206
#10 0x00007ffff71d59f7 in ?? ()
#11 0x00007fffffffd470 in ?? ()
#12 0x00007ffff71d522b in ?? ()
#13 0x00007fffffffd470 in ?? ()
#14 0x00007ffff71d4017 in ?? ()
#15 0x0000555555e60c70 in ?? ()
#16 0x00007ffff71d4000 in ?? ()
#17 0x0000555555cca298 in _PyRuntime ()
#18 0x00007ffff7fac0b8 in ?? ()
#19 0x00007ffff7fac160 in ?? ()
#20 0x00005555557ca1c0 in _PyEval_EvalFrameDefault (tstate=0xcdcdcdcdcdcdcdcd, frame=0x555555cca298 <_PyRuntime+331064>, throwflag=-842150451)
    at Python/generated_cases.c.h:5598
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

Here are the outputs from running with PYTHON_OPT_DEBUG=4 and PYTHON_LLTRACE=4, since they are too long I've attached them as files:
opt_debug2.txt
lltrace2.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.0a0 (heads/main-dirty:6bf1c0ab349, Jul 21 2025, 20:28:08) [GCC 14.2.0]

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.