From a48c1caa9e26e4453ae8277dbf940e405df7ca5b Mon Sep 17 00:00:00 2001 From: Norm Brandinger Date: Fri, 17 Apr 2026 14:42:25 -0400 Subject: [PATCH] opentelemetry: support building on non-x86 architectures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building the new opentelemetry module on aarch64 (Jetson Thor, Debian trixie, GCC 14) fails with: pt.h:92:9: error: 'atomic_t' does not name a type Looking into it, this turns out to be an issue on every non-x86 architecture, not just aarch64. Root cause opentelemetry.cpp is a C++ translation unit, but it includes C headers from the core (pt.h, statistics.h, ...). Those headers reach atomic.h, which defines atomic_t two different ways: 1. When HAVE_STDATOMIC is set, via the C11 keyword: typedef _Atomic(unsigned long) atomic_t; 2. Otherwise, via a hand-rolled fallback: typedef struct { volatile unsigned long counter; } atomic_t; `_Atomic` is a C-only keyword and is not part of C++. The module currently undef's HAVE_STDATOMIC at the top of the C++ source so that atomic.h takes path (2). That works on __CPU_i386 and __CPU_x86_64, which are the architectures where atomic.h provides the fallback typedef. On aarch64, arm, ppc, mips, riscv, s390x, and others, atomic.h has no fallback, so atomic_t ends up undefined and every header that references it (pt.h, statistics.h) fails to compile. Proposed approach Rather than undef'ing HAVE_STDATOMIC — which forces a path that does not exist for most architectures — another option is to keep HAVE_STDATOMIC in whatever state the build system picked (it is set by Makefile.defs or compiler auto-detection as appropriate) and shim the C11 `_Atomic(T)` keyword to std::atomic for this C++ translation unit: #ifdef __cplusplus #include #define _Atomic(T) std::atomic #endif atomic.h's typedef now resolves to `std::atomic atomic_t` under C++ on every architecture. Why this should be ABI-safe `std::atomic` and C11 `_Atomic(T)` have identical memory layout on every GCC/Clang target that supports both — it is a guarantee of the standard library implementation (std::atomic is `alignas(T) T` when T is lock-free, which mirrors _Atomic(T)). The C headers only ever treat atomic_t as an opaque type — they take its address and pass it to helper functions like atomic_inc() / atomic_set(), and they never read .counter directly from a C++ compile unit. So even though the C side may see path (2)'s struct layout and the C++ side now sees std::atomic's layout, the two interoperate correctly because neither side reaches into the other's representation. If the maintainers prefer a different approach (for example, extending atomic.h with a fallback for the remaining architectures), we are happy to adjust. Tested on - aarch64 (Jetson Thor, Debian trixie, GCC 14): the original failure is gone; opentelemetry.so builds and loads into a running OpenSIPS; spans export to an OTLP/HTTP collector; SIP attributes (sip.method, sip.call_id, sip.ruri, net.peer.ip, ...) populate correctly on spans produced by request and event routes. - x86_64 (Debian trixie, GCC 14.2.0): no regression. The module still builds and links cleanly against the Debian-packaged opentelemetry-cpp 1.19.0 and libabsl-dev. --- modules/opentelemetry/opentelemetry.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/opentelemetry/opentelemetry.cpp b/modules/opentelemetry/opentelemetry.cpp index fc5a0940b2b..5124869485b 100644 --- a/modules/opentelemetry/opentelemetry.cpp +++ b/modules/opentelemetry/opentelemetry.cpp @@ -52,8 +52,16 @@ namespace otelotlp = opentelemetry::exporter::otlp; #ifdef __cplusplus /* Relax C-only headers for C++ compilation. */ #define class class_keyword -#undef HAVE_STDATOMIC #undef HAVE_GENERICS +/* atomic.h defines atomic_t using the C11 keyword `_Atomic(T)` when + * HAVE_STDATOMIC is set. `_Atomic` is C-only and not valid in C++, so + * we shim it to std::atomic for this C++ translation unit. With + * the shim, atomic.h's typedef resolves as + * typedef std::atomic atomic_t; + * on every architecture. HAVE_STDATOMIC itself is set by Makefile.defs + * or compiler auto-detection, so no change to its value is needed here. */ +#include +#define _Atomic(T) std::atomic #endif extern "C" {