python / python/cpython

[Free-threading] `assert(!_Py_IsImmortal(op))` failure when BRC merge queue races with `sys.intern`

Aperta
#152,276 0 commenti 1 reazione 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

interpreter-core topic-free-threading type-bug
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug report

Bug description:

In the free-threaded build, there is a race condition where an object can be queued for Biased Reference Counting (BRC) merging, but become immortal before the queue is processed. This causes a fatal C-level assertion failure:

assert.h assertion failed at Objects/object.c:467 in Py_ssize_t _Py_ExplicitMergeRefcount(PyObject *, Py_ssize_t): !_Py_IsImmortal(op)

*** Check failure stack trace: ***
    @     _Py_ExplicitMergeRefcount
    @     merge_queued_objects
    @     _Py_brc_merge_refcounts
    @     _Py_HandlePending
    @     _PyEval_EvalFrameDefault

Reproduction. Fails when running under ASAN/TSAN and the free-threading build:

import threading
import sys
def test_race():
    # 1 million strings will trap Thread A inside map() for milliseconds,
    # giving Thread B plenty of time to queue references to strings that 
    # Thread A hasn't interned yet.
    strings = ["race_string_massive_" + str(j) for j in range(1000000)]
    
    # Give Thread B a copy of the list.
    shared = list(strings)
    
    def thread_b_func():
        # Thread B clears its list, reducing the shared refcount to 0.
        # Since Thread B is not the owner, they are placed in Thread A's merge queue.
        shared.clear()
    tb = threading.Thread(target=thread_b_func)
    tb.start()
    # Thread A executes entirely in C for milliseconds.
    # Strings are queued by Thread B, AND THEN made immortal by sys.intern!
    list(map(sys.intern, strings))
    tb.join()
if __name__ == "__main__":
    test_race()
CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs
  • gh-152277

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia da Objects/object.c in _Py_ExplicitMergeRefcount e segui il percorso di chiamate menzionato di merge_queued_objects, _Py_brc_merge_refcounts e _Py_HandlePending. Riproduci la race condition con ASAN o TSAN usando la build free-threaded, quindi confronta il comportamento e la risoluzione nella PR collegata gh-152277.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, python
Ambito
backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
30/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.