Skip to content

Documentation: libunwind/libgcc_s exception handling conflict causing crashes #6330

@PavelGuzenfeld

Description

@PavelGuzenfeld

Documentation / FAQ Request

This is not a bug report against Fast-DDS itself — this is a request to add a troubleshooting entry for a well-known Linux ecosystem issue that frequently affects Fast-DDS users, since Fast-DDS relies heavily on C++ exception handling.

We are submitting a documentation PR to eProsima/Fast-DDS-docs with the troubleshooting entry.

Problem Description

When libunwind is loaded into a process before libgcc_s.so.1, C++ exception handling breaks. The _Unwind_* symbols provided by libunwind shadow those from libgcc_s, but the two libraries use incompatible _Unwind_Context struct layouts. This causes segfaults or crashes whenever C++ exceptions are thrown or caught.

Because Fast-DDS makes extensive use of C++ exceptions, it is one of the most visible victims of this conflict — users see crashes originating in Fast-DDS exception handling code, even though the root cause is in the unwinder layer beneath it.

How It Manifests

  • Segmentation faults during C++ exception handling (throw/catch)
  • Crashes in _Unwind_RaiseException, __cxa_throw, or related frames
  • Intermittent or immediate crashes in Fast-DDS participant creation or discovery

Environment

  • Architecture: x86_64 (the struct layout mismatch is architecture-specific)
  • OS: Linux, particularly in Docker containers
  • Common trigger: ROS 2 environments where GStreamer (or other multimedia/profiling packages) transitively pulls in libunwind, which gets loaded before libgcc_s.so.1

Root Cause

glibc's pthread_exit (and pthread_cancel) implementation hardcodes dlopen("libgcc_s.so.1") to obtain _Unwind_* symbols for stack unwinding. However, if libunwind is already loaded in the process (e.g., as a transitive dependency), the dynamic linker resolves _Unwind_* symbols to libunwind's versions instead. The two libraries define _Unwind_Context with different struct layouts, so passing one library's context to the other's functions causes memory corruption and crashes.

This is a long-standing ecosystem issue, documented since at least 2004.

Workaround

Force libgcc_s.so.1 to be loaded first using LD_PRELOAD:

export LD_PRELOAD=/lib/x86_64-linux-gnu/libgcc_s.so.1

For Docker containers:

ENV LD_PRELOAD=/lib/x86_64-linux-gnu/libgcc_s.so.1

Upstream References

  • Ubuntu Bug #1960005 — libunwind conflicts with libgcc_s unwinder
  • LLVM #90041 — related unwinder symbol conflicts
  • GCC/glibc patches from 2004 discussing the dlopen("libgcc_s.so.1") hardcoding in pthread_cancel/pthread_exit

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions