python / python/cpython

Assertion failure: `!_PyFrame_IsIncomplete(frame->f_frame)`

Ouverte
#149,110 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

interpreter-core topic-free-threading 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?

It's possible to cause an abort on a free-threaded build even with PYTHON_GIL=1 by running the code below (only reproduces with free threading enabled builds).

I attempted to replicate the trigger without pdb (using sys.monitoring directly, frame trace setters, sys.settrace, Bdb directly) without success. pdb's specific call chain seems necessary to reliably trigger it.

MRE:

from threading import Thread
import sys, pdb
sys.stdin = open("/dev/null")

# ONE shared Pdb instance so threads call set_trace on the SAME one
shared_pdb = pdb.Pdb(mode='inline', backend='monitoring', colorize=False)

def thread_target():
    shared_pdb.set_trace(sys._getframe().f_back)

def set_trace():
    return sys._getframe().f_back

for x in range(5):
    threads = []
    for x in range(50):
        threads.append(Thread(target=thread_target))
        threads.append(Thread(target=set_trace))
        threads.append(Thread(target=sys._clear_internal_caches))

    for t in threads:
        t.start()
        sys._clear_internal_caches()
    for t in threads:
        t.join()

print("NO ABORT")

Backtrace:

python: Objects/frameobject.c:2400: PyFrameObject *PyFrame_GetBack(PyFrameObject *): Assertion `!_PyFrame_IsIncomplete(frame->f_frame)' failed.

Thread 23 "Thread-22 (thre" 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  0x0000555555b50d29 in PyFrame_GetBack (frame=frame@entry=0x7bffcc160410) at Objects/frameobject.c:2400
#8  0x0000555555b58c76 in frame_back_get_impl (self=0x7bffcc160410) at Objects/frameobject.c:1119
#9  frame_back_get (self=<optimized out>, _unused_context=<optimized out>) at Objects/clinic/frameobject.c.h:212
#10 0x0000555555c2cfb4 in _PyObject_GenericGetAttrWithDict (obj=0x7bffcc160410, name=0x7bffb60c0610, dict=0x0, suppress=0) at Objects/object.c:1924
#11 0x0000555555c2cab3 in _PyObject_GetAttrStackRef (v=0x7bffcc160410, name=0x7bffb60c0610) at Objects/object.c:1367
#12 0x0000555555edc322 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:8041
#13 0x0000555555ea8d04 in _PyEval_EvalFrame (tstate=0x7bffb4249010, frame=0x7e8ff709e328, throwflag=0) at ./Include/internal/pycore_ceval.h:118
#14 _PyEval_Vector (tstate=0x7bffb4249010, func=0x7bffb64cb1b0, locals=0x0, args=0x7bff9d4b9720, argcount=1, kwnames=0x0) at Python/ceval.c:2179
#15 0x0000555555ac6030 in _PyObject_VectorcallTstate (tstate=tstate@entry=0x7bffb4249010, callable=callable@entry=0x7bffb64cb1b0, args=0x7bff9d4b9720, nargsf=nargsf@entry=1,
    kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:144
#16 0x0000555555acbf7f in _PyObject_VectorcallPrepend (tstate=<optimized out>, callable=<optimized out>, arg=<error reading variable: Cannot access memory at address 0x6>,
    args=<optimized out>, nargsf=0, kwnames=<optimized out>) at Objects/call.c:855
#17 0x0000555555f6b113 in _PyObject_VectorcallTstate (tstate=0x7bffb4249010, callable=0x7bffc82200d0, args=0x7bff9a2ab6c0, nargsf=22, kwnames=0x0) at ./Include/internal/pycore_call.h:144
#18 context_run (self=0x7bffb757cc10, args=args@entry=0x7bff9a2a96b0, nargs=nargs@entry=1, kwnames=kwnames@entry=0x0) at Python/context.c:727
#19 0x0000555555af812d in method_vectorcall_FASTCALL_KEYWORDS (func=func@entry=0x7bffb60a8820, args=args@entry=0x7bff9a2a96a8, nargsf=nargsf@entry=9223372036854775810,
    kwnames=kwnames@entry=0x0) at Objects/descrobject.c:421
#20 0x0000555555ac6030 in _PyObject_VectorcallTstate (tstate=0x7bffb4249010, callable=0x7bffb60a8820, args=0x7bff9a2a96a8, nargsf=9223372036854775810, kwnames=0x0)
    at ./Include/internal/pycore_call.h:144
#21 0x0000555555ea9e3b in _Py_VectorCallInstrumentation_StackRefSteal (callable=..., arguments=arguments@entry=0x7e8ff709e2f8, total_args=total_args@entry=2, kwnames=kwnames@entry=...,
    call_instrumentation=false, frame=frame@entry=0x7e8ff709e298, this_instr=0x7bffc81901fe, tstate=0x7bffb4249010) at Python/ceval.c:775
#22 0x0000555555ee754d in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:1841
#23 0x0000555555ea8d04 in _PyEval_EvalFrame (tstate=0x7bffb4249010, frame=0x7e8ff709e220, throwflag=0) at ./Include/internal/pycore_ceval.h:118
#24 _PyEval_Vector (tstate=0x7bffb4249010, func=0x7bffb64cb290, locals=0x0, args=0x7bff9d4b8220, argcount=1, kwnames=0x0) at Python/ceval.c:2179
#25 0x0000555555ac6030 in _PyObject_VectorcallTstate (tstate=tstate@entry=0x7bffb4249010, callable=callable@entry=0x7bffb64cb290, args=0x7bff9d4b8220, nargsf=nargsf@entry=1,
    kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:144
#26 0x0000555555acbf7f in _PyObject_VectorcallPrepend (tstate=<optimized out>, callable=<optimized out>, arg=<error reading variable: Cannot access memory at address 0x6>,
    args=<optimized out>, nargsf=0, kwnames=<optimized out>) at Objects/call.c:855
#27 0x0000555555ac8802 in _PyVectorcall_Call (tstate=<optimized out>, func=<optimized out>, callable=<optimized out>, tuple=0x55555695f428 <_PyRuntime+173928>, kwargs=<optimized out>)
    at Objects/call.c:273
#28 0x00005555562c9019 in thread_run (boot_raw=boot_raw@entry=0x7bffb41f08d0) at ./Modules/_threadmodule.c:387
#29 0x000055555610e226 in pythread_wrapper (arg=0x7bffb4010b50) at Python/thread_pthread.h:234
#30 0x00005555558a034b in asan_thread_start(void*) ()

Found using fusil by @vstinner.

CPython versions tested on:

CPython main branch, 3.15

Operating systems tested on:

Linux

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

Python 3.15.0a7+ free-threading build (heads/main:4d0e8ee649c, Mar 29 2026, 23:20:29) [Clang 21.1.2 (2ubuntu6)]

Linked PRs
  • gh-156001

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.

Piste de recherche

Commencez par le reproducer et le backtrace, puis inspectez Objects/frameobject.c autour de PyFrame_GetBack ainsi que la chaîne d’appels pdb/sys.monitoring décrite dans l’issue. Exécutez le MRE sur un build free-threaded de CPython 3.15 ; le travail est considéré comme terminé lorsque l’abort ne se produit plus avec la charge de travail multi-threadée signalée et qu’une couverture de régression appropriée est ajoutée.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
backend
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
25/100

Recevez les nouvelles issues par e-mail

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