Repository navigation
Segfault/aborts calling readline.set_completer_delims in threads in a free-threaded build #126895
Copy link
Copy link
Closed
Labels
3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-free-threadingtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
Crash report
What happened?
Calling difflib._test in threads in a free-threaded build (with PYTHON_GIL=0) will result in aborts or segfaults, apparently related to memory issues:
from threading import Thread
import difflib
for x in range(100):
Thread(target=difflib._test, args=()).start()Segfault backtrace:
Thread 92 "python" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffeca7e4640 (LWP 631239)]
0x00007ffff7d3f743 in unlink_chunk (p=p@entry=0x555555f56c00, av=0x7ffff7eb8c80 <main_arena>) at ./malloc/malloc.c:1634
1634 ./malloc/malloc.c: No such file or directory.
(gdb) bt
#0 0x00007ffff7d3f743 in unlink_chunk (p=p@entry=0x555555f56c00, av=0x7ffff7eb8c80 <main_arena>)
at ./malloc/malloc.c:1634
#1 0x00007ffff7d40d2b in _int_free (av=0x7ffff7eb8c80 <main_arena>, p=0x555555f528a0,
have_lock=<optimized out>) at ./malloc/malloc.c:4616
#2 0x00007ffff7d43453 in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3391
#3 0x000055555570ed2c in _PyMem_RawFree (_unused_ctx=<optimized out>, ptr=<optimized out>)
at Objects/obmalloc.c:90
#4 0x0000555555713955 in _PyMem_DebugRawFree (ctx=0x555555cdb8f8 <_PyRuntime+824>, p=0x555555f528c0)
at Objects/obmalloc.c:2767
#5 0x000055555572c462 in PyMem_RawFree (ptr=ptr@entry=0x555555f528c0) at Objects/obmalloc.c:971
#6 0x00005555559527fc in free_threadstate (tstate=tstate@entry=0x555555f528c0) at Python/pystate.c:1411
#7 0x00005555559549c0 in _PyThreadState_DeleteCurrent (tstate=tstate@entry=0x555555f528c0)
at Python/pystate.c:1834
#8 0x0000555555a11b74 in thread_run (boot_raw=boot_raw@entry=0x555555f52870)
at ./Modules/_threadmodule.c:355
#9 0x0000555555974fdb in pythread_wrapper (arg=<optimized out>) at Python/thread_pthread.h:242
#10 0x00007ffff7d32ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#11 0x00007ffff7dc4850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81Abort 1 backtrace:
Thread 78 "python" received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffed17f2640 (LWP 633651)]
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140732413191744) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140732413191744) at ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=6, threadid=140732413191744) at ./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=140732413191744, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3 0x00007ffff7ce0476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4 0x00007ffff7cc67f3 in __GI_abort () at ./stdlib/abort.c:79
#5 0x00007ffff7d27676 in __libc_message (action=action@entry=do_abort,
fmt=fmt@entry=0x7ffff7e79b77 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#6 0x00007ffff7d3ecfc in malloc_printerr (
str=str@entry=0x7ffff7e7c6c0 "free(): unaligned chunk detected in tcache 2") at ./malloc/malloc.c:5664
#7 0x00007ffff7d40e3f in _int_free (av=0x7ffff7eb8c80 <main_arena>, p=0x555555dc79b0, have_lock=0)
at ./malloc/malloc.c:4471
#8 0x00007ffff7d43453 in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3391
#9 0x00007ffff41d4a2b in readline_set_completer_delims (module=<optimized out>, string=<optimized out>)
at ./Modules/readline.c:593
#10 0x00005555557021ef in cfunction_vectorcall_O (
func=<built-in method set_completer_delims of module object at remote 0x2000297b920>,
args=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/methodobject.c:523
#11 0x000055555567cc55 in _PyObject_VectorcallTstate (tstate=0x555555f15bc0,
callable=<built-in method set_completer_delims of module object at remote 0x2000297b920>,
args=0x7ffed17f15a8, nargsf=9223372036854775809, kwnames=0x0) at ./Include/internal/pycore_call.h:167
#12 0x000055555567cd74 in PyObject_Vectorcall (
callable=callable@entry=<built-in method set_completer_delims of module object at remote 0x2000297b920>,
args=args@entry=0x7ffed17f15a8, nargsf=<optimized out>, kwnames=kwnames@entry=0x0) at Objects/call.c:327
#13 0x00005555558441f7 in _PyEval_EvalFrameDefault (tstate=tstate@entry=0x555555f15bc0,
frame=<optimized out>, throwflag=throwflag@entry=0) at Python/generated_cases.c.h:955
#14 0x0000555555872978 in _PyEval_EvalFrame (throwflag=0, frame=<optimized out>, tstate=0x555555f15bc0)
at ./Include/internal/pycore_ceval.h:116Abort 2 backtrace:
Thread 43 "python" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff54ff9640 (LWP 636245)]
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140734619424320) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140734619424320) at ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=6, threadid=140734619424320) at ./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=140734619424320, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3 0x00007ffff7ce0476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4 0x00007ffff7cc67f3 in __GI_abort () at ./stdlib/abort.c:79
#5 0x00007ffff7d27676 in __libc_message (action=action@entry=do_abort,
fmt=fmt@entry=0x7ffff7e79b77 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#6 0x00007ffff7d3ecfc in malloc_printerr (
str=str@entry=0x7ffff7e7cf20 "tcache_thread_shutdown(): unaligned tcache chunk detected")
at ./malloc/malloc.c:5664
#7 0x00007ffff7d436c4 in tcache_thread_shutdown () at ./malloc/malloc.c:3224
#8 __malloc_arena_thread_freeres () at ./malloc/arena.c:1003
#9 0x00007ffff7d461ca in __libc_thread_freeres () at ./malloc/thread-freeres.c:44
#10 0x00007ffff7d3294f in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:456
#11 0x00007ffff7dc4850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81Found using fusil by @vstinner.
CPython versions tested on:
3.13, CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.14.0a1+ experimental free-threading build (heads/main-dirty:612ac283b81, Nov 16 2024, 01:37:56) [GCC 11.4.0]
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-free-threadingtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Activity
picnixz commentedon Nov 16, 2024
The
_testfunction is only doing:I think the issue is either with doctest or the imports, not with difflib itself.
cc @ZeroIntensity
devdanzin commentedon Nov 16, 2024
I believe this is due to
doctestusingpdb, which seems to cause all sorts of segfaults and aborts when called from threads. Comment the marked lines out for a different crash.So maybe the issue is just that
pdbisn't free-threading ready?Edit: here's a collection of errors this causes:
picnixz commentedon Nov 16, 2024
@gaogaotiantian Is there a plan to make pdb free-threaded friendly or not? if so, how can we help, if not what should we do for this issue?
ZeroIntensity commentedon Nov 16, 2024
I'll wait for Tian's input, but I'm happy to spend a few hours covering pdb in locks if we need to.
gaogaotiantian commentedon Nov 16, 2024
pdbis a pure Python module, without any black magic (ctypes, changing the code object, etc.). It should not be possible for it to crash (segfault) CPython, free-threaded build or not. If pdb crashes free-threaded build, that means free-threaded build has a bug, notpdb.From the code above, the conclusion I can get is
pdbtriggered a crash, and we don't know why. Protectingpdbwith lock might hide the crash, but it does not solve the problem. We should not be able to crash CPython with pure Python code.Also,
pdbdoes not support multi-threading debugging at this point. It's really slow to move it forward for any relatively new features. That being said, I don't think it's a good time to try to protect it with locks because we need to deal with multithreading in the future.ZeroIntensity commentedon Nov 16, 2024
Does it use some weird frames APIs (e.g.
sys._getframe) by any chance? Those aren't thread safe IIRC.devdanzin commentedon Nov 16, 2024
The culprit seems to be
readline, whichpdbuses:Seems to fail with the same errors as the original code.
6 remaining items
gaogaotiantian commentedon Nov 16, 2024
I would be a little bit more careful when dealing with
readline, because it relies on some global variables of the readline library, so we can't simply put everything thread or module local. The variables starting withrl_are the extern global variables exposed by readline itself. Also, we support libedit which has a slightly different interface. The module is not the most stable one in our stdlib so tread carefully :)ZeroIntensity commentedon Nov 16, 2024
If it has global state, I doubt the functions themself are thread safe. In that case, we probably should just mark it as needing the GIL.
[-]Segfault/aborts calling `difflib._test` in threads in a free-threaded build[/-][+]Segfault/aborts calling `readline.set_completer_delims` in threads in a free-threaded build[/+]vstinner commentedon Nov 18, 2024
Or add
@critical_sectionor another lock on functions which are known to not be thread-safe.ZeroIntensity commentedon Nov 18, 2024
That wouldn't work for subinterpreters, would it?
pythongh-126895: fix readline module in free-threaded build
gh-126895: Fix readline module in free-threaded build (#131208)
colesbury commentedon Mar 17, 2025
This is fixed in
main, but not backported to 3.13.pythongh-126895: Fix readline module in free-threaded build (python#1…
devdanzin commentedon Apr 19, 2025
This seems to have regressed in 3.13 somehow, unless it's a different issue coming from the same code. I'm getting aborts and segfaults with the following code:
Abort backtrace 1:
Segfault backtrace 1:
Segfault backtrace 2:
Segfault backtrace 3:
python -VV:devdanzin commentedon Apr 19, 2025
Oh, never mind, according to #131208 (comment) this wasn't backported to 3.13. Sorry for the noise.
pythongh-153291: Fix data race in readline.get_completer() and get_pr…
gh-153291: Fix data race in readline.get_completer() and get_pre_inpu…
[3.15] gh-153291: Fix data race in readline.get_completer() and get_p…