Python built with ./configure --with-pydebug --disable-gil and gcc -Og on Alpine Linux (Python built with musl C library).
Example of crash on "AMD64 Alpine Linux NoGIL 3.x" buildbot: https://buildbot.python.org/#/builders/1819/builds/1699
Script:
import threading
def recurse():
return recurse()
def outer():
try:
recurse()
except RecursionError:
pass
w = threading.Thread(target=outer)
w.start()
w.join()
print('end of main thread')
gdb traceback:
(gdb) where
#0 0x0000560e9bedb871 in _Py_Dealloc (op=0x20004156010) at Objects/object.c:3277
#1 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156010) at Objects/object.c:444
#2 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
lineno=lineno@entry=520, op=0x20004156010) at ./Include/refcount.h:359
#3 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520
#4 0x0000560e9c088e30 in tb_dealloc (op=0x20004156070) at Python/traceback.c:245
#5 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156070) at Objects/object.c:3300
#6 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156070) at Objects/object.c:444
#7 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
lineno=lineno@entry=520, op=0x20004156070) at ./Include/refcount.h:359
#8 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520
#9 0x0000560e9c088e30 in tb_dealloc (op=0x200041560d0) at Python/traceback.c:245
#10 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x200041560d0) at Objects/object.c:3300
#11 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x200041560d0) at Objects/object.c:444
#12 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
lineno=lineno@entry=520, op=0x200041560d0) at ./Include/refcount.h:359
#13 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520
#14 0x0000560e9c088e30 in tb_dealloc (op=0x20004156130) at Python/traceback.c:245
#15 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156130) at Objects/object.c:3300
#16 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156130) at Objects/object.c:444
#17 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
lineno=lineno@entry=520, op=0x20004156130) at ./Include/refcount.h:359
#18 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520
#19 0x0000560e9c088e30 in tb_dealloc (op=0x20004156190) at Python/traceback.c:245
#20 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156190) at Objects/object.c:3300
#21 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156190) at Objects/object.c:444
#22 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
lineno=lineno@entry=520, op=0x20004156190) at ./Include/refcount.h:359
#23 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520
#24 0x0000560e9c088e30 in tb_dealloc (op=0x200041561f0) at Python/traceback.c:245
#25 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x200041561f0) at Objects/object.c:3300
#26 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x200041561f0) at Objects/object.c:444
#27 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
lineno=lineno@entry=520, op=0x200041561f0) at ./Include/refcount.h:359
#28 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520
#29 0x0000560e9c088e30 in tb_dealloc (op=0x20004156250) at Python/traceback.c:245
#30 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156250) at Objects/object.c:3300
#31 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156250) at Objects/object.c:444
#32 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h",
(...)
#3751 0x0000560e9be774fb in PyObject_Call (callable=<optimized out>, args=<optimized out>, kwargs=<optimized out>)
at Objects/call.c:373
#3752 0x0000560e9c10f6ef in thread_run (boot_raw=boot_raw@entry=0x20000030920) at ./Modules/_threadmodule.c:388
#3753 0x0000560e9c0874c0 in pythread_wrapper (arg=<optimized out>) at Python/thread_pthread.h:234
#3754 0x00007f484b327573 in start (p=<optimized out>) at src/thread/pthread_create.c:207
#3755 0x00007f484b328ec1 in __clone () at src/thread/x86_64/clone.s:22
Backtrace stopped: frame did not save the PC
(gdb) info threads
Id Target Id Frame
1 LWP 9804 "python" __cp_end () at src/thread/x86_64/syscall_cp.s:29
* 2 LWP 9807 "Thread-1 (outer" 0x0000560e9bedb871 in _Py_Dealloc (op=0x20004156010) at Objects/object.c:3277
_Py_Dealloc() has the Trashcan mechanism which is supposed to avoid long chain of _Py_Dealloc() calls to reduce the stack memory consumption. But it seems like it doesn't work on Alpine Linux (Python built with musl C library).
gdb variables in the _Py_Dealloc() frame:
(gdb) p type->tp_name
$6 = 0x555ba66f5c7f "traceback"
(gdb) p gc_flag
$7 = 16384
In the parent _Py_Dealloc() frame:
(gdb) p type->tp_name
$9 = 0x555ba66f5c7f "traceback"
(gdb) p gc_flag
$10 = <optimized out>
(gdb) p margin
$11 = 115
In the first _Py_Dealloc() frame (outer):
(gdb) p margin
$12 = 119
(gdb) p type->tp_name
$13 = 0x555ba66e9dcd "RecursionError"
(gdb) p gc_flag
$14 = <optimized out>
(gdb) p type->tp_flags & (1UL << 14) # gc_flag
$15 = 16384
On a regular build (without Free Threading), the script works as expected, it displays:
Linked PRs
Python built with ./configure --with-pydebug --disable-gil and gcc -Og on Alpine Linux (Python built with musl C library).
Example of crash on "AMD64 Alpine Linux NoGIL 3.x" buildbot: https://buildbot.python.org/#/builders/1819/builds/1699
Script:
gdb traceback:
(gdb) where #0 0x0000560e9bedb871 in _Py_Dealloc (op=0x20004156010) at Objects/object.c:3277 #1 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156010) at Objects/object.c:444 #2 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", lineno=lineno@entry=520, op=0x20004156010) at ./Include/refcount.h:359 #3 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520 #4 0x0000560e9c088e30 in tb_dealloc (op=0x20004156070) at Python/traceback.c:245 #5 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156070) at Objects/object.c:3300 #6 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156070) at Objects/object.c:444 #7 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", lineno=lineno@entry=520, op=0x20004156070) at ./Include/refcount.h:359 #8 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520 #9 0x0000560e9c088e30 in tb_dealloc (op=0x200041560d0) at Python/traceback.c:245 #10 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x200041560d0) at Objects/object.c:3300 #11 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x200041560d0) at Objects/object.c:444 #12 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", lineno=lineno@entry=520, op=0x200041560d0) at ./Include/refcount.h:359 #13 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520 #14 0x0000560e9c088e30 in tb_dealloc (op=0x20004156130) at Python/traceback.c:245 #15 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156130) at Objects/object.c:3300 #16 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156130) at Objects/object.c:444 #17 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", lineno=lineno@entry=520, op=0x20004156130) at ./Include/refcount.h:359 #18 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520 #19 0x0000560e9c088e30 in tb_dealloc (op=0x20004156190) at Python/traceback.c:245 #20 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156190) at Objects/object.c:3300 #21 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156190) at Objects/object.c:444 #22 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", lineno=lineno@entry=520, op=0x20004156190) at ./Include/refcount.h:359 #23 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520 #24 0x0000560e9c088e30 in tb_dealloc (op=0x200041561f0) at Python/traceback.c:245 #25 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x200041561f0) at Objects/object.c:3300 #26 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x200041561f0) at Objects/object.c:444 #27 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", lineno=lineno@entry=520, op=0x200041561f0) at ./Include/refcount.h:359 #28 0x0000560e9c088af7 in Py_XDECREF (op=<optimized out>) at ./Include/refcount.h:520 #29 0x0000560e9c088e30 in tb_dealloc (op=0x20004156250) at Python/traceback.c:245 #30 0x0000560e9bedb8e0 in _Py_Dealloc (op=0x20004156250) at Objects/object.c:3300 #31 0x0000560e9bedb9ef in _Py_MergeZeroLocalRefcount (op=op@entry=0x20004156250) at Objects/object.c:444 #32 0x0000560e9c088aaf in Py_DECREF (filename=filename@entry=0x560e9c12425b "./Include/refcount.h", (...) #3751 0x0000560e9be774fb in PyObject_Call (callable=<optimized out>, args=<optimized out>, kwargs=<optimized out>) at Objects/call.c:373 #3752 0x0000560e9c10f6ef in thread_run (boot_raw=boot_raw@entry=0x20000030920) at ./Modules/_threadmodule.c:388 #3753 0x0000560e9c0874c0 in pythread_wrapper (arg=<optimized out>) at Python/thread_pthread.h:234 #3754 0x00007f484b327573 in start (p=<optimized out>) at src/thread/pthread_create.c:207 #3755 0x00007f484b328ec1 in __clone () at src/thread/x86_64/clone.s:22 Backtrace stopped: frame did not save the PC (gdb) info threads Id Target Id Frame 1 LWP 9804 "python" __cp_end () at src/thread/x86_64/syscall_cp.s:29 * 2 LWP 9807 "Thread-1 (outer" 0x0000560e9bedb871 in _Py_Dealloc (op=0x20004156010) at Objects/object.c:3277_Py_Dealloc() has the Trashcan mechanism which is supposed to avoid long chain of _Py_Dealloc() calls to reduce the stack memory consumption. But it seems like it doesn't work on Alpine Linux (Python built with musl C library).
gdb variables in the _Py_Dealloc() frame:
In the parent _Py_Dealloc() frame:
In the first _Py_Dealloc() frame (outer):
On a regular build (without Free Threading), the script works as expected, it displays:
Linked PRs