Skip to content

EngineCrash [2026.06.08-RC] at [CBeamLaser::FireInternal] (bug report and gdb poke around assisted by LLM) #3018

Description

@Wabuo

Description

The engine crashes with SIGABRT due to a libstdc++ hardening assertion failure (__glibcxx_assert_fail) inside CQuadField::GetQuadsOnRay. A laser beam's length calculation yields an inverted negative distance value, which violates the downstream std::clamp invariant (lo <= hi).

Environment

  • OS: Linux (Arch Linux / CachyOS package build)
  • Engine Build: recoil-engine-rc (systemwide_managed_by_pkgmngr-2026.06.08-RC.local) (build from the AUR PKGBUILD (full build instructions used are below)
  • Game: Beyond All Reason
  • Toolchain State: Built with GCC runtime assertions enabled (-D_GLIBCXX_ASSERTIONS)

Build Instructions used

cmake3 -S "${srcdir}/${pkgname%-git}"  -G Ninja \
            -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
            -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O3 -g -DNDEBUG -fdiagnostics-color=always" \
            -DCMAKE_C_FLAGS_RELWITHDEBINFO="-O3 -g -DNDEBUG -fdiagnostics-color=always" \
            -DCMAKE_BUILD_TYPE=RELWITHDEBINFO \
            -DAI_TYPES=NATIVE \
            -DINSTALL_PORTABLE=ON \
            -DCMAKE_USE_RELATIVE_PATHS:BOOL=1 \
            -DBINDIR:PATH=./ \
            -DLIBDIR:PATH=./ \
            -DDATADIR:PATH=./ \
            -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
### Disabled in favor of using the settings from makepkg.conf
#           -DCMAKE_TOOLCHAIN_FILE="toolchain/clang_x86_64-pc-linux-gnu.cmake" \

# V=1 make VERBOSE=1 -j1
        cd "${srcdir}"; ninja #--verbose

And here what makepkg.conf introduces

#-- Compiler and Linker Flags
#CPPFLAGS=""
CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
        -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security \
        -fstack-clash-protection -fcf-protection \
        -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
         -Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto"
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"

Context & Diagnostic Data

Inspecting the core dump isolates the frame parameter conflict inside CBeamLaser::FireInternal where the negative distance value originates:

(gdb) frame 7
#7  CBeamLaser::FireInternal (...) at rts/Sim/Weapons/BeamLaser.cpp:360
360             TraceRay::TraceRayShields(this, curPos, curDir, beamLength, hitShields);

(gdb) info locals
beamLength = -82.403389
maxLength = 215
hitColQuery = { b0 = 1, b1 = 1, t0 = 83.6559067, t1 = 108.723846, ... }

An intersection query successfully found a collision boundary at hitColQuery.t0 = 83.6559067. However, beamLength evaluates to -82.403389.

The difference between the query distance and the resulting length maps directly to the weapon's muzzle piece offset from the origin axis:
83.6559067 - 82.403389 = 1.2525177

The terms appear to be inverted during calculation (muzzleOffset - hitColQuery.t0 instead of hitColQuery.t0 - muzzleOffset), generating a negative scalar value. This negative value is passed directly down into CQuadField::GetQuadsOnRay:

(gdb) frame 5
#5  CQuadField::GetQuadsOnRay(QuadFieldQuery&, float3 const&, float3 const&, float) at rts/Sim/Misc/QuadField.cpp:264
264             t0 = std::clamp(t0, 0.0f, length);

(gdb) info args
length = -82.403389

Because length is negative, calling std::clamp(t0, 0.0f, length) passes a high bound that is lower than the low bound (0.0f). On hardened distributions, this immediately triggers a runtime abort via __glibcxx_assert_fail.

Call Stack

#0  0x00007f05f74adfbb pthread_kill () from /usr/lib/libc.so.6
#1  0x00007f05f7444c88 raise () from /usr/lib/libc.so.6
#2  0x00007f05f7425795 abort () from /usr/lib/libc.so.6
#3  0x00007f05f789e059 _ZSt21__glibcxx_assert_fail... () from /usr/lib/libstdc++.so.6
#4  0x00005595fe675be0 std::clamp<float>(...)
#5  CQuadField::GetQuadsOnRay(...) at QuadField.cpp:264
#6  TraceRay::TraceRayShields(...) at TraceRay.cpp:343
#7  CBeamLaser::FireInternal(...) at BeamLaser.cpp:360
#8  CWeapon::Fire(bool) at Weapon.cpp:227
#9  CWeapon::UpdateSalvo() at Weapon.cpp:228
#10 CBeamLaser::Update() at BeamLaser.cpp:212

full output of me poking around in gdb

https://gist.github.com/Wabuo/d26242b7724c6dca6e9f10ccd905dd8d

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenginecrashHard engine crashes (segfaults, assertion failures) with stacktraces

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions