Repository navigation
Description
What happened?
FXServer Linux 38317: SIGSEGV during txAdmin monitor shutdown in musl get_meta
Environment
- Ubuntu Server 24.04, amd64
- FXServer Linux x86-64 build
38317, with the bundled txAdmin monitor - Temporary systemd service running as an unprivileged user with
PrivateNetwork=yes - No game configuration, Qbox, custom resources, database connection, or public listeners
The test used a separate, audited extraction of the official artifact. Absolute symlink targets in the bundled Alpine tree were converted to relative paths pointing to their packaged equivalents. The regular files, including the executable and libraries, matched the official archive byte for byte. The crash has not yet been reproduced with an unmodified extraction of the official artifact.
Minimal reproduction
- Start
run.shin txAdmin monitor mode without+execor a game configuration. Bind the monitor to127.0.0.1:40121inside the service's private network namespace. - Use
KillSignal=SIGTERM,KillMode=mixed, andTimeoutStopSec=10sin the temporary systemd unit. - After the first HTTP 200, check the monitor once per second for 15 additional checks. All 15 returned HTTP 200. The game port
30121never listened. - Stop the unit with
systemctl stop.
Expected: The monitor shuts down cleanly and the service exits successfully.
Observed: txAdmin logged that it received SIGTERM and started shutting down. The main process then exited with Result=core-dump, ExecMainCode=3, and ExecMainStatus=11. In the GDB capture, systemctl stop returned after 4.797 seconds. In the equivalent run without GDB, systemd recorded the main process exiting on SIGSEGV 4.796 seconds after it began stopping the unit, before the 10-second timeout.
First-fault evidence
A prior strace capture recorded SEGV_MAPERR at address 0x10. GDB subsequently stopped at the first SIGSEGV in the affected thread and captured the following selected frames. The offsets below are file offsets derived from the mapped regions. GDB then resumed execution with the original signal.
| Frame | Module | File offset | Symbol or context |
|---|---|---|---|
| 0 | ld-musl-x86_64.so.1 |
0x45acd |
get_meta+0x42 |
| 1 | ld-musl-x86_64.so.1 |
0x45b9f |
__libc_free |
| 2 | libnode22.so |
0x483c298 |
node::NodePlatform::~NodePlatform()+0x68, the return site after the isolate table destructor call |
| 6 | libnode22.so |
0x483c3ce |
Return site after the complete NodePlatform destructor call, inside the deleting destructor |
| 9–10 | libcitizen-scripting-node.so |
0x46e30, 0x46e43 |
Unresolved routine and return site after an indirect virtual call |
| 12–13 | ld-musl-x86_64.so.1 |
0x41b31, 0x1409e |
__funcs_on_exit, exit |
| 14, 16 | libnode22.so |
0x467d179, 0x467d1cf |
Return sites in node::Exit and node::DefaultProcessExitHandlerInternal |
The unwind also contained anonymous mappings and addresses outside executable ELF segments. Those entries were excluded from function attribution, and the table does not establish an uninterrupted call chain.
Static findings and open questions
Confirmed from the exact artifact: libnode22.so file offset 0x483c298 maps to ELF virtual address 0x483d298. The instruction immediately preceding it, at 0x483d293, calls the destructor of the hash table that maps V8 isolates to their platform delegate and per-isolate data. The table destructor has a sized operator delete call for a 40-byte node at ELF virtual address 0x48402dc and a tail call to sized operator delete for externally allocated bucket storage at 0x484036c. It also releases shared references that can invoke further destructors indirectly. The separate deletion of the NodePlatform object itself occurs after the complete destructor returns.
Unresolved: The fault occurred in musl while looking up allocator metadata during free. The available stack does not identify which table cleanup operation reached __libc_free. An invalid pointer, double free, or earlier memory corruption are possible explanations. The evidence does not distinguish them or establish which component introduced the invalid state.
PR #4294 discusses isolate and libuv teardown ordering during JavaScript resource lifecycle changes. Issue #4306 reports a different Linux SIGSEGV signature involving bundled libnode22.so. They are related context. This report concerns shutdown of the standalone txAdmin monitor and has a different reproduction and fault signature.
Build IDs and request
| Module | ELF build ID |
|---|---|
libnode22.so |
5e5a737448fc9ea1a48a7fb3e1440574f5552815 |
libcitizen-scripting-node.so |
3d315fcb53fee9f0 |
ld-musl-x86_64.so.1 |
8cd6ae4cc97899e68e9c22264f9235e3f90e0d95 |
The packaged musl debug file matched its build ID. The other ELF files reference libnode22.so.dbg and libcitizen-scripting-node.so.dbg through .gnu_debuglink. Matching debug files were unavailable for this analysis.
Could you provide the official .dbg files for those exact build IDs or resolve the remaining frames internally? The most useful result would be to identify the teardown operation that reached __libc_free, including the indirect call in libcitizen-scripting-node.so if it is part of that path.
Expected result
FXServer should shut down gracefully when receiving SIGTERM, exiting with status code 0 without triggering a segmentation fault, leaving orphaned processes, or requiring forced termination.
Reproduction steps
- Set up Ubuntu Server 24.04 amd64 with FXServer Linux build 38317.
- Extract the official FXServer artifact into an isolated test directory. For this reproduction, absolute Alpine symlinks were converted to equivalent internal relative targets.
- Launch
run.shin txAdmin monitor mode without+exec, game configuration, Qbox, or custom resources. - Run FXServer as an unprivileged user under systemd with
PrivateNetwork=yes,KillSignal=SIGTERM,KillMode=mixed, andTimeoutStopSec=10s. - Confirm txAdmin responds with HTTP 200 on
127.0.0.1:40121for 15 consecutive checks. - Execute
systemctl stopfor the temporary FXServer service. - Observe that the main FXServer process terminates with
SIGSEGVapproximately 4.8 seconds after shutdown begins, reportingResult=core-dump,ExecMainCode=3, andExecMainStatus=11. - Using GDB, observe the crash at
get_meta+0x42in the bundled musl loader, with stack frames involving__libc_freeandnode::NodePlatform::~NodePlatform().
Importancy
Crash
Area(s)
FXServer, ScRT: JS
Specific version(s)
FXServer Linux x86-64 builds 37872 and 38317 (Ubuntu Server 24.04 amd64)
Additional information
The crash is reproducible on both FXServer Linux builds 37872 and 38317 during txAdmin monitor shutdown, without loading game resources or a database.
GDB captured the first SIGSEGV in the bundled musl allocator at get_meta+0x42, reached through __libc_free. The stack includes node::NodePlatform::~NodePlatform() in libnode22.so, along with frames from libcitizen-scripting-node.so and the process exit handlers.
Relevant build IDs:
libnode22.so:5e5a737448fc9ea1a48a7fb3e1440574f5552815libcitizen-scripting-node.so:3d315fcb53fee9f0ld-musl-x86_64.so.1:8cd6ae4cc97899e68e9c22264f9235e3f90e0d95
The test used an isolated extraction with absolute Alpine symlinks converted to equivalent relative paths. Executable and library contents matched the official archive. The issue has not yet been reproduced using an unmodified official runtime environment.
Could the Cfx.re team provide matching libnode22.so.dbg and libcitizen-scripting-node.so.dbg symbols, or help identify the teardown operation responsible for the invalid memory access?
Possibly related, but with different reproduction conditions:
Activity