The stackdumper function tools.cpp is registered as a signal handler. It uses backtrace and backtrace_symbols to print a stack trace. The backtrace_symbols function internally uses mallocwhich is not async-signal-safe and such a function cannot be safely used in a signal handler. In practice, it can cause a deadlock and the function will never exit.
The buggy code exists in all versions of the project but I confirmed a deadlock behavior on v1.3.0.0-BETA3.
Example execution:
$ bin_unix/native_client --loadmap=ac_x45
parsing commandline argument 1: "--loadmap=ac_x45"
Using home directory: profile/
writing to file: profile/clientlog.txt
init: sdl (2.0.10)
init: net (1.3.6)
init: world (-(1203))
init: video: sdl
init: video: mode
init: video: misc
init: gl
Renderer: llvmpipe (LLVM 12.0.0, 256 bits) (Mesa/X.org)
Driver: 3.1 Mesa 21.0.3
init: console
init: sound
Audio devices: OpenAL Soft
Sound: OpenAL Soft / OpenAL Soft (OpenAL Community)
Driver: 1.1 ALSOFT 1.19.1
init: cfg
init: models
init: docs
init: localconnect
own IP: 0.0.0.0, censored own IP: 0.0.0.0, --, clock offset -454695 hours -2 minutes
auth challenge: SERVINFOCHALLENGE<(0) cn: 0 c: 0.0.0.0 (--) s: 0.0.0.0:0 3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29 st: 0 ct: 27281702 (-2674965)>
init: mainloop
could not read "private/authprivate.cfg"
Beware: This is a BETA version of AssaultCube v1.3
Thank you for testing AssaultCube and helping us to release the new version!
resolving hostname packages.cubers.net failed (0.0.0.0)
successfully pinged 0 media servers, 1 failure, 0 disabled
local server failed to load map "packages/maps/official/ac_x45", error: invalid HX_ARTIST record
WARNING: rebuildtexlists() fixed 0|2|27 missing entries
while reading map at 2: type 12 out of range
while reading map at 2: unexpected end of file
world error -2
read map packages/maps/official/ac_x45.cgz rev 0 (26 milliseconds)
Douze (AC-Version) by makkE - layout by stanze
malformed emb config
malformed emb config
loaded textures (6 milliseconds)
loaded mapmodels (8 milliseconds)
loaded mapsounds (0 milliseconds)
can't find entity spawn spot! (64, 64)
game mode is "TDM"
unresolved problems occurred during load_world(), warning: 0x210
can't find entity spawn spot! (64, 64)
can't find entity spawn spot! (64, 64)
stacktrace:
bin_unix/native_client() [0x539012]
/lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7f5c91af3210]
bin_unix/native_client() [0x46ff7e]
bin_unix/native_client() [0x4a5c46]
bin_unix/native_client() [0x4a69a3]
bin_unix/native_client(main+0x1622) [0x480c12]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7f5c91ad40b3]
bin_unix/native_client() [0x4174de]
AssaultCube error (11) ()
corrupted size vs. prev_size
stacktrace:
$ sudo gdb -q --pid 5537
Attaching to process 5537
[New LWP 5538]
[New LWP 5545]
[New LWP 5546]
[New LWP 5547]
[New LWP 5550]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
__lll_lock_wait_private (futex=0x7f5c91c98b80 <main_arena>) at ./lowlevellock.c:35
35 ./lowlevellock.c: No such file or directory.
(gdb) bt
#0 __lll_lock_wait_private (futex=0x7f5c91c98b80 <main_arena>) at ./lowlevellock.c:35
#1 0x00007f5c91b4a4ab in __GI___libc_malloc (bytes=bytes@entry=2069) at malloc.c:3064
#2 0x00007f5c91bdd3e6 in __backtrace_symbols (array=0x7fff239d6860, size=<optimized out>) at backtracesyms.c:69
#3 0x0000000000539024 in signalbinder::stackdumper (sig=6) at tools.cpp:390
#4 <signal handler called>
#5 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#6 0x00007f5c91ad2859 in __GI_abort () at abort.c:79
#7 0x00007f5c91b3d3ee in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f5c91c67285 "%s\n")
at ../sysdeps/posix/libc_fatal.c:155
#8 0x00007f5c91b4547c in malloc_printerr (str=str@entry=0x7f5c91c6543a "corrupted size vs. prev_size") at malloc.c:5347
#9 0x00007f5c91b45aeb in unlink_chunk (p=p@entry=0x1326f80, av=0x7f5c91c98b80 <main_arena>) at malloc.c:1454
#10 0x00007f5c91b45c2f in malloc_consolidate (av=av@entry=0x7f5c91c98b80 <main_arena>) at malloc.c:4502
#11 0x00007f5c91b47160 in _int_free (av=0x7f5c91c98b80 <main_arena>, p=0xf9b550, have_lock=<optimized out>) at malloc.c:4400
#12 0x00007f5c9232a1b8 in _XFreeDisplayStructure () from /lib/x86_64-linux-gnu/libX11.so.6
#13 0x00007f5c923173a1 in XCloseDisplay () from /lib/x86_64-linux-gnu/libX11.so.6
#14 0x00007f5c92286d45 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#15 0x00007f5c92259886 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#16 0x00007f5c921c9b8a in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#17 0x00007f5c921c9c7c in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#18 0x000000000047842b in cleanup (msg=0x7fff239d75c0 "AssaultCube error (11) ()\n") at main.cpp:29
#19 0x0000000000478a35 in fatal (s=0x5bbc98 "AssaultCube error (%d)") at main.cpp:72
#20 0x00000000005390cc in signalbinder::stackdumper (sig=11) at tools.cpp:400
#21 <signal handler called>
#22 0x000000000046ff7e in rendermapmodels () at entities.cpp:110
#23 0x00000000004a5c46 in drawminimap (w=1440, h=792) at rendergl.cpp:859
#24 0x00000000004a69a3 in gl_drawframe (w=1440, h=792, changelod=0.455351174, curfps=27.3210697, elapsed=102) at rendergl.cpp:1026
#25 0x0000000000480c12 in main (argc=2, argv=0x7fff239d8488) at main.cpp:1537
The
stackdumper
functiontools.cpp
is registered as a signal handler. It usesbacktrace
andbacktrace_symbols
to print a stack trace. Thebacktrace_symbols
function internally usesmalloc
which is not async-signal-safe and such a function cannot be safely used in a signal handler. In practice, it can cause a deadlock and the function will never exit.The buggy code exists in all versions of the project but I confirmed a deadlock behavior on v1.3.0.0-BETA3.
Example execution: