From c3ae2c4b50aecd00687e9c914c87b1b24a7febe2 Mon Sep 17 00:00:00 2001 From: Russell McGuire Date: Tue, 7 Jul 2026 13:00:31 -0700 Subject: [PATCH] Fix incompatible strerror_r for non-gnu/windows libc Signed-off-by: Russell McGuire --- source/utils/ze_logger.cpp | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/source/utils/ze_logger.cpp b/source/utils/ze_logger.cpp index 76d22c90..1049dd6e 100644 --- a/source/utils/ze_logger.cpp +++ b/source/utils/ze_logger.cpp @@ -105,20 +105,41 @@ const char *levelColor(LogLevel l) { } // Thread-safe, portable errno-to-string conversion. -// MSVC deprecates strerror() in favour of strerror_s(); POSIX provides strerror_r(). +// strerror_r has two incompatible POSIX signatures depending on libc: +// - GNU: char *strerror_r(int, char *, size_t) (glibc with _GNU_SOURCE) +// - XSI: int strerror_r(int, char *, size_t) (musl, Bionic, uClibc, POSIX) +// _GNU_SOURCE is not a reliable discriminator — it requests GNU extensions but +// only glibc honours it for strerror_r. We let overload resolution pick the +// right handler based on the actual return type the compiler sees, so the +// code is correct under any libc without preprocessor guesswork. +// MSVC uses strerror_s. +#ifndef _WIN32 +// Mark both overloads as "may be unused" — only one matches strerror_r's +// signature for any given libc, so the other is intentionally dead code. +#if defined(__GNUC__) || defined(__clang__) +#define ZE_LOGGER_MAYBE_UNUSED __attribute__((unused)) +#else +#define ZE_LOGGER_MAYBE_UNUSED +#endif +// XSI variant: returns int (0 on success); message is in `buf`. +static ZE_LOGGER_MAYBE_UNUSED std::string strerrorRDispatch(int /*ret*/, char *buf) { + return std::string(buf); +} +// GNU variant: returns char* that may or may not point at `buf`. +static ZE_LOGGER_MAYBE_UNUSED std::string strerrorRDispatch(char *ret, char *buf) { + return ret ? std::string(ret) : std::string(buf); +} +#undef ZE_LOGGER_MAYBE_UNUSED +#endif + static std::string errnoToString(int err) { char buf[256]; + buf[0] = '\0'; #ifdef _WIN32 strerror_s(buf, sizeof(buf), err); return buf; -#elif defined(_GNU_SOURCE) - // GNU strerror_r returns char* (may or may not use buf) - const char *result = strerror_r(err, buf, sizeof(buf)); - return result ? result : buf; #else - // XSI-compliant strerror_r returns int - strerror_r(err, buf, sizeof(buf)); - return buf; + return strerrorRDispatch(strerror_r(err, buf, sizeof(buf)), buf); #endif }