Concrete debugging plan (what I’d ask Murat to run)
Capture a real backtrace, not just frame 0:
ulimit -c unlimited
./Slicer # reproduce crash
coredumpctl gdb # or: gdb ./bin/SlicerApp-real core
(gdb) bt full
(gdb) info sharedlibrary
(gdb) info proc mappings
Frame 0 alone tells us nothing about the caller; bt full will show which Slicer/VTK code fed garbage into the regex.
2. Identify which libstdc++ is actually loaded at the crash site:
If that fixes it, walk printenv | grep -E 'LD_|PYTHON|CONDA' to find the offending var.
4. Check the locale path (cheap and worth ruling out):
locale ; locale -a | grep -i utf
Bisect the factory builds.download.slicer.org keeps weekly Linux previews; install three or four (e.g. 2026-04-01, 2026-04-15, 2026-04-28, 2026-05-05) and find the first that crashes on Murat’s box. Then git log --oneline <good_rev>..<bad_rev> on Slicer + look at Superbuild revisions of VTK/Qt for that span. (The thread does not yet identify a regressing commit, despite what the WebFetch summary claimed.)
If frame 0’s bt full shows the regex string is empty / null / garbage, the bug is most likely on the Slicer side (a recent change that passes an uninitialized std::string to std::regex), not glibc. Same fix shape as the 2022 vtkSlicerVolumeRenderingLogic::CreateROINode regression in 2022-01-10.
Fix paths
If libstdc++ mismatch is confirmed (step 2): ship a vendored libstdc++.so.6 in Slicer-5.11/lib/ and add it to the launcher’s LD_LIBRARY_PATH ahead of system. Slicer used to do this; if it was dropped, that’s the regression. Cheapest verification: cp /usr/lib/.../libstdc++.so.6 lib/Slicer-5.11/ on the build machine, re‑run, see if the crash goes away.
If it’s a conda/Anaconda env pollution: add a launcher guard that scrubs LD_LIBRARY_PATH entries containing anaconda/miniconda/conda before exec, and document it.
If it’s a real null‑string fed into std::regex: fix the call site (bt full will name it). No glibc involvement.
For chir.set’s Wayland/GLX issue (separate): have Slicer’s launcher detect XDG_SESSION_TYPE=wayland + Qt5 and default QT_QPA_PLATFORM=xcb, since Slicer’s Qt5 has no working Wayland path with the VTK GL contexts.
Want me to draft the launcher patch for the Wayland default, or to scaffold a slicer-debug-libs.sh script that runs steps 1–4 in one go?
Okay, after our discussion at the developer meeting @lassoan suggested that a workaround would be to disable surface smoothing in the volume renderer:
I tested and I can get the crash with the current preview build if it turn on this feature, so it does seem to be the thing that triggers the bad code path. @muratmaga can you confirm?
We also realized that the builds with the crash are actually using the new VTK version, so this is probably what triggered the underlying issue. I’ll try some of the things Claude suggested and see if I can get any more info on any underlying glibc issues.
So after some testing it looks like there’s a C++ issue that I won’t try to explain that happens on linux and has to do with the way VTK compiles by default.
Probably we can patch it with these flags when building VTK:
It would be better for VTK to be built like this by default, but we can do this as a workaround if we want.
For the very short run, just turning off the surface smoothing in volume rendering is a patch.
The underlying issue is illustrated by just running this script. Maybe we can refine this here and then file an issue in the VTK gitlab with the suggested fix.
exouser@sdp-test-volume-render:~/Downloads$ cat ~/repo.sh
#!/usr/bin/env bash
# Reproducer: VTK 9.6 std::regex ODR exposure on Linux/ELF.
# Paste into any Linux box with g++, python3-venv, and an older g++ available.
set -euo pipefail
OLDGCC=${OLDGCC:-g++-9} # override if g++-9 missing; try g++-11 or g++-13
if ! command -v "$OLDGCC" >/dev/null; then
cat >&2 <<EOF
need $OLDGCC in PATH.
Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y $OLDGCC
(older series may need 'universe' enabled, or try OLDGCC=g++-11)
Fedora/RHEL: sudo dnf install -y gcc-toolset-11-gcc-c++
then: scl enable gcc-toolset-11 -- bash (and re-run this script)
Arch: sudo pacman -S gcc11 (then OLDGCC=g++-11 $0)
override the version on the command line, e.g.: OLDGCC=g++-11 $0
EOF
exit 1
fi
W=$(mktemp -d); cd "$W"
echo "workdir: $W"
echo "old g++: $($OLDGCC --version | head -1)"
echo "default g++: $(g++ --version | head -1)"
cat > companion.cxx <<'CXX'
#include <regex>
extern "C" void companion_touch() {
static std::regex r("(a)|(b)|(c)"); (void)r;
}
CXX
"$OLDGCC" -shared -fPIC -O2 companion.cxx -o libcompanion.so
python3 -m venv .venv && . .venv/bin/activate
pip install --quiet 'vtk>=9.6'
PYCALL='import vtk; r=vtk.vtkImageReader2(); r.ComputeInternalFileName(0); print("VTK",vtk.VTK_VERSION,"ok:",repr(r.GetInternalFileName()))'
echo; echo "=== 1. bare run ==="
python -c "$PYCALL"
echo; echo "=== 2. companion preloaded (LD_PRELOAD) ==="
err=$(mktemp)
set +e
LD_PRELOAD=$PWD/libcompanion.so python -c "$PYCALL" 2> >(tee "$err" >&2)
rc=$?
set -e
echo
if [ $rc -eq 0 ]; then
echo ">>> RESULT: did NOT reproduce (clean exit)."
echo ">>> Try a wider GCC gap: OLDGCC=g++-9 (or g++-7) $0"
elif [ $rc -ge 128 ]; then
sig=$((rc - 128)); name=$(kill -l "$sig" 2>/dev/null || echo "?")
case "$name" in
SEGV|ABRT|BUS|ILL|FPE)
echo ">>> RESULT: BUG REPRODUCED."
echo ">>> Process killed by SIG$name (signal $sig, exit $rc)."
if grep -q 'bad_alloc\|terminate called' "$err"; then
echo ">>> libstdc++ aborted from an uncaught exception (e.g. std::bad_alloc)."
echo ">>> This is the same ODR-drift class as the SIGSEGV seen in the field."
echo ">>> _Compiler is built with one layout, walked with another;"
echo ">>> the corrupted state can deref a bad pointer (SIGSEGV) OR request"
echo ">>> an absurd allocation (bad_alloc -> terminate -> SIGABRT)."
else
echo ">>> Same crash class as Murat's field SIGSEGV in vtkStringFormatter."
fi
;;
*)
echo ">>> RESULT: killed by SIG$name (signal $sig); inconclusive."
;;
esac
else
echo ">>> RESULT: exited $rc (non-zero but not a signal). Not a crash; probably a Python-level error."
fi
rm -f "$err"
echo; echo "=== 3. which library wins the _Compiler template symbol ==="
for env in "" "LD_PRELOAD=$PWD/libcompanion.so"; do
echo "-- env: ${env:-none}"
env $env gdb --batch -q \
-ex 'set breakpoint pending on' \
-ex 'b vtkImageReader2::ComputeInternalFileName' \
-ex 'run' \
-ex "info sym 'std::__detail::_Compiler<std::__cxx11::regex_traits<char> >::_M_alternative()'" \
--args python -c "$PYCALL" 2>/dev/null | grep -E '^\$|in section|libcompanion|libvtk|libstdc' || true
done
@pieper Can you try uninstalling the VTK Python package that Slicer builds and instead pip install the VTK whl from PyPI? I would suspect there are some differences in how we configure and build the whl versus VTK.
Does the issue happen in Slicer core with no extensions installed with its self-built VTK whl or does a Slicer extension install a specific VTK whl that pulls from PyPI that is using a different _GLIBCXX_USE_CXX11_ABI?
Latest VTK on PyPI only provide x86_64 whls that are manylinux_2_17 as they provide manylinux_2_28 whl for ARM64 Linux only. vtk · PyPI
I’ve checked and libQtWebEngineCore.so. contains incorrectly exported std symbols until Qt-6.6, but the problem got fixed in Qt-6.7. So, the simplest fix the crash in Slicer would be to upgrade to Qt-6.7 or higher.
It is nice if we also fix this in VTK, because that way we avoid crashes in the future when any other software component incorrectly exports symbols. The flags that were proposed above (CMAKE_CXX_VISIBILITY_PRESET, CMAKE_VISIBILITY_INLINES_HIDDEN, etc.) were already set, but Claude suggested a small, localized change that made the global std:: symbols disappear. – @Sam_Horvath or @ebrahim could you patch VTK on factory with this commit and create a nightly linux build with it to confirm the fix and test that there are no regressions?