Skip to content

Segfault in free-threaded build from interaction of nested list/tuple repr #132707

@devdanzin

Description

@devdanzin

Crash report

What happened?

It's possible to segfault or abort a free-threaded build with the following code, not sure the same issue accounts for both:

import sys

# Not sure what this weird_cls dance is doing, but it seems necessary somehow
class weird_cls(int): pass
weird_instances = {"weird_int_empty": weird_cls()}
weird_classes = {"weird_int": weird_cls}
weird_instances["weird_int_10**default_max_str_digits+1"] = weird_classes["weird_int"](10 ** (sys.int_info.default_max_str_digits + 1))

import gc
from threading import Thread
from time import sleep

def stress_list():
    sleep(0.1)
    target.append(None)
    repr(gc.get_objects())
    target.append(None)

for x in range(40):
    target = []
    alive = []
    for x in range(15):
        alive.append(Thread(target=stress_list, args=()))
    for t in alive:
        t.start()
    gc.collect()

The cause needs to be diagnosed properly, any help is welcome :)

Segfault backtrace:

Thread 82 "Thread-81 (stre" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fff8c0ac640 (LWP 3996396)]
0x0000555555cc0686 in _Py_TYPE (ob=0x0) at ./Include/object.h:270
270             return ob->ob_type;

#0  0x0000555555cc0686 in _Py_TYPE (ob=0x0) at ./Include/object.h:270
#1  PyUnicodeWriter_WriteRepr (writer=writer@entry=0x7fff4a090850, obj=0x0)
    at Objects/unicodeobject.c:13947
#2  0x0000555555bfaebb in tuple_repr (self=(<str_ascii_iterator at remote 0x7fff440f0a60>, 0x0))
    at Objects/tupleobject.c:271
#3  0x0000555555b8949a in PyObject_Repr (v=(<str_ascii_iterator at remote 0x7fff440f0a60>, 0x0))
    at Objects/object.c:776
#4  0x0000555555cc06a1 in PyUnicodeWriter_WriteRepr (writer=writer@entry=0x7fff4a0907f0, obj=0x0)
    at Objects/unicodeobject.c:13951
#5  0x0000555555aeba03 in list_repr_impl (v=0x7fff4a0c1d50) at Objects/listobject.c:606
#6  list_repr (
    self=[<Name(id='self', ctx=<Load at remote 0x7fffb63421e0>, lineno=1, col_offset=18, end_lineno=1, end_col_offset=22) at remote 0x7fff44450620>, <Attribute(value=<...>, attr='run', ctx=<...>, lineno=1, col_offset=18, end_lineno=1, end_col_offset=26) at remote 0x7fff444505c0>, <Name(id='self', ctx=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=4) at remote 0x7fff44450560>, <Attribute(value=<...>, attr='_context', ctx=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=13) at remote 0x7fff44450500>, <Attribute(value=<...>, attr='run', ctx=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=17) at remote 0x7fff444504a0>, <Call(func=<...>, args=[<...>], keywords=[], lineno=1, col_offset=0, end_lineno=1, end_col_offset=27) at remote 0x7fff44450440>, <Expr(value=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=27) at remote 0x7fff444503e0>, <Module(body=[<...>], type_ignores=[]) at remote 0x7fff44450380>, <suppress(_exceptions=(<type at remote 0x555556550d00>, <type at remote 0x55...(truncated)) at Objects/listobject.c:633
#7  0x0000555555b8949a in PyObject_Repr (
    v=[<Name(id='self', ctx=<Load at remote 0x7fffb63421e0>, lineno=1, col_offset=18, end_lineno=1, end_col_offset=22) at remote 0x7fff44450620>, <Attribute(value=<...>, attr='run', ctx=<...>, lineno=1, col_offset=18, end_lineno=1, end_col_offset=26) at remote 0x7fff444505c0>, <Name(id='self', ctx=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=4) at remote 0x7fff44450560>, <Attribute(value=<...>, attr='_context', ctx=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=13) at remote 0x7fff44450500>, <Attribute(valu--Type <RET> for more, q to quit, c to continue without paging--c
e=<...>, attr='run', ctx=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=17) at remote 0x7fff444504a0>, <Call(func=<...>, args=[<...>], keywords=[], lineno=1, col_offset=0, end_lineno=1, end_col_offset=27) at remote 0x7fff44450440>, <Expr(value=<...>, lineno=1, col_offset=0, end_lineno=1, end_col_offset=27) at remote 0x7fff444503e0>, <Module(body=[<...>], type_ignores=[]) at remote 0x7fff44450380>, <suppress(_exceptions=(<type at remote 0x555556550d00>, <type at remote 0x55...(truncated)) at Objects/object.c:776
#8  0x0000555555e07abf in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:2306
#9  0x0000555555ddcf53 in _PyEval_EvalFrame (tstate=0x52900037a210, frame=0x5290003c5328, throwflag=0) at ./Include/internal/pycore_ceval.h:119
#10 _PyEval_Vector (tstate=0x52900037a210, func=0x7fffb4a9a110, locals=0x0, args=<optimized out>, argcount=1, kwnames=0x0) at Python/ceval.c:1917
#11 0x0000555555a4f42b in _PyObject_VectorcallTstate (tstate=0x52900037a210, callable=<function at remote 0x7fffb4a9a110>, args=0x0, nargsf=0, nargsf@entry=1, kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:169
#12 0x0000555555a4ccbf in method_vectorcall (method=<optimized out>, args=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/classobject.c:72
#13 0x0000555555e8005b in _PyObject_VectorcallTstate (tstate=0x52900037a210, callable=<method at remote 0x7fff4a0c0790>, args=0x7fff8c0ab6d8, nargsf=0, kwnames=0x0) at ./Include/internal/pycore_call.h:169
#14 context_run (self=<_contextvars.Context at remote 0x7fffb4675a70>, args=<optimized out>, nargs=<optimized out>, kwnames=0x0) at Python/context.c:728
#15 0x0000555555e0a3e7 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:3551
#16 0x0000555555ddcf53 in _PyEval_EvalFrame (tstate=0x52900037a210, frame=0x5290003c5220, throwflag=0) at ./Include/internal/pycore_ceval.h:119
#17 _PyEval_Vector (tstate=0x52900037a210, func=0x7fffb4a9a1f0, locals=0x0, args=<optimized out>, argcount=1, kwnames=0x0) at Python/ceval.c:1917
#18 0x0000555555a4f42b in _PyObject_VectorcallTstate (tstate=0x52900037a210, callable=<function at remote 0x7fffb4a9a1f0>, args=0x0, nargsf=0, nargsf@entry=1, kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:169
#19 0x0000555555a4ccbf in method_vectorcall (method=<optimized out>, args=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/classobject.c:72
#20 0x000055555612e2ee in thread_run (boot_raw=boot_raw@entry=0x507000006770) at ./Modules/_threadmodule.c:353
#21 0x0000555555fe7a8d in pythread_wrapper (arg=<optimized out>) at Python/thread_pthread.h:242
#22 0x000055555585cd47 in asan_thread_start(void*) ()
#23 0x00007ffff7cfeac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#24 0x00007ffff7d90850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Abort backtrace:

python: Objects/listobject.c:81: void ensure_shared_on_resize(PyListObject *): Assertion `Py_REFCNT(self) == 1 || PyMutex_IsLocked(&_PyObject_CAST(self)->ob_mutex)' failed.

Thread 61 "Thread-60 (stre" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff922e6640 (LWP 3780304)]
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140735645902400) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.

#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140735645902400) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140735645902400) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140735645902400, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7cac476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7c927f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7c9271b in __assert_fail_base (
    fmt=0x7ffff7e47130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
    assertion=0x5555561fec80 <str> "Py_REFCNT(self) == 1 || PyMutex_IsLocked(&_PyObject_CAST(self)->ob_mutex)", file=0x5555561fde40 <str> "Objects/listobject.c", line=81, function=<optimized out>)
    at ./assert/assert.c:94
#6  0x00007ffff7ca3e96 in __GI___assert_fail (
    assertion=0x5555561fec80 <str> "Py_REFCNT(self) == 1 || PyMutex_IsLocked(&_PyObject_CAST(self)->ob_mutex)", file=0x5555561fde40 <str> "Objects/listobject.c", line=line@entry=81,
    function=0x5555561fed00 <__PRETTY_FUNCTION__.ensure_shared_on_resize> "void ensure_shared_on_resize(PyListObject *)") at ./assert/assert.c:103
#7  0x0000555555ae4f9f in ensure_shared_on_resize (self=0x7fffba0c2c50) at Objects/listobject.c:81
#8  list_resize (self=self@entry=0x7fffba0c2c50, newsize=newsize@entry=1) at Objects/listobject.c:142
#9  0x0000555555ae48ee in _PyList_AppendTakeRefListResize (self=0x7fffba0c2c50,
    newitem='self._target(*self._args, **self._kwargs)') at Objects/listobject.c:523
#10 0x0000555555df77fe in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>,
    throwflag=<optimized out>) at Python/generated_cases.c.h:7617
#11 0x0000555555aaac20 in _PyEval_EvalFrame (tstate=0x529000370210, frame=<optimized out>,
    throwflag=<optimized out>) at ./Include/internal/pycore_ceval.h:119
#12 gen_send_ex2 (gen=0x7fffbab601d0, arg=arg@entry=0x0, presult=presult@entry=0x7fff922e3f88,
    exc=exc@entry=0, closing=closing@entry=0) at Objects/genobject.c:259
#13 0x0000555555aa56bc in gen_iternext (self=<unknown at remote 0x39ae94>) at Objects/genobject.c:634
#14 0x0000555555e067bd in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>,
--Type <RET> for more, q to quit, c to continue without paging--
    throwflag=<optimized out>) at Python/generated_cases.c.h:5471
#15 0x0000555555ddcb03 in _PyEval_EvalFrame (tstate=0x529000370210, frame=0x52900038e408, throwflag=0)
    at ./Include/internal/pycore_ceval.h:119
#16 _PyEval_Vector (tstate=0x529000370210, func=0x7fffb6716f30, locals=0x0, args=<optimized out>,
    argcount=1, kwnames=0x0) at Python/ceval.c:1913
#17 0x0000555555a4316b in _PyObject_VectorcallTstate (tstate=0x529000370210,
    callable=callable@entry=<function at remote 0x7fffb6716f30>, args=0x39aed0, nargsf=6,
    nargsf@entry=9223372036854775809, kwnames=<unknown at remote 0x7fff922e3090>, kwnames@entry=0x0)
    at ./Include/internal/pycore_call.h:169
#18 0x0000555555a45f11 in PyObject_CallOneArg (func=<optimized out>,
    arg=ValueError('Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit',)) at Objects/call.c:395
#19 0x0000555555fa0e1f in _PyErr_Display (
    file=file@entry=<_io.TextIOWrapper(mode='w') at remote 0x7fffb4368c10>, unused=<optimized out>,
    value=value@entry=ValueError('Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit',), tb=tb@entry=<traceback at remote 0x7fffba0c09d0>)
    at Python/pythonrun.c:1157
#20 0x000055555612b43c in thread_excepthook_file (
    file=<_io.TextIOWrapper(mode='w') at remote 0x7fffb4368c10>, exc_type=<type at remote 0x55555654eca0>,
    exc_value=ValueError('Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit',), exc_traceback=<traceback at remote 0x7fffba0c09d0>,
    thread=<optimized out>) at ./Modules/_threadmodule.c:2204
#21 thread_excepthook (module=<optimized out>,
    args=args@entry=<_thread._ExceptHookArgs at remote 0x7fffba0d05c0>) at ./Modules/_threadmodule.c:2283
#22 0x0000555555e071db in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>,
    throwflag=<optimized out>) at Python/generated_cases.c.h:2280
#23 0x0000555555ddcb03 in _PyEval_EvalFrame (tstate=0x529000370210, frame=0x52900038e220, throwflag=0)

Found using fusil by @vstinner.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

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

Python 3.14.0a7+ experimental free-threading build (heads/main:c7f6535e4a3, Apr 15 2025, 09:09:58) [GCC 11.4.0]

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)topic-free-threadingtype-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