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
    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