Skip to content

Commit 426e96a

Browse files
authored
Fix incompatible strerror_r for non-gnu/windows libc (#493)
Signed-off-by: Russell McGuire <russell.w.mcguire@intel.com>
1 parent d3b3efb commit 426e96a

1 file changed

Lines changed: 29 additions & 8 deletions

File tree

‎source/utils/ze_logger.cpp‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,41 @@ const char *levelColor(LogLevel l) {
105105
}
106106

107107
// Thread-safe, portable errno-to-string conversion.
108-
// MSVC deprecates strerror() in favour of strerror_s(); POSIX provides strerror_r().
108+
// strerror_r has two incompatible POSIX signatures depending on libc:
109+
// - GNU: char *strerror_r(int, char *, size_t) (glibc with _GNU_SOURCE)
110+
// - XSI: int strerror_r(int, char *, size_t) (musl, Bionic, uClibc, POSIX)
111+
// _GNU_SOURCE is not a reliable discriminator — it requests GNU extensions but
112+
// only glibc honours it for strerror_r. We let overload resolution pick the
113+
// right handler based on the actual return type the compiler sees, so the
114+
// code is correct under any libc without preprocessor guesswork.
115+
// MSVC uses strerror_s.
116+
#ifndef _WIN32
117+
// Mark both overloads as "may be unused" — only one matches strerror_r's
118+
// signature for any given libc, so the other is intentionally dead code.
119+
#if defined(__GNUC__) || defined(__clang__)
120+
#define ZE_LOGGER_MAYBE_UNUSED __attribute__((unused))
121+
#else
122+
#define ZE_LOGGER_MAYBE_UNUSED
123+
#endif
124+
// XSI variant: returns int (0 on success); message is in `buf`.
125+
static ZE_LOGGER_MAYBE_UNUSED std::string strerrorRDispatch(int /*ret*/, char *buf) {
126+
return std::string(buf);
127+
}
128+
// GNU variant: returns char* that may or may not point at `buf`.
129+
static ZE_LOGGER_MAYBE_UNUSED std::string strerrorRDispatch(char *ret, char *buf) {
130+
return ret ? std::string(ret) : std::string(buf);
131+
}
132+
#undef ZE_LOGGER_MAYBE_UNUSED
133+
#endif
134+
109135
static std::string errnoToString(int err) {
110136
char buf[256];
137+
buf[0] = '\0';
111138
#ifdef _WIN32
112139
strerror_s(buf, sizeof(buf), err);
113140
return buf;
114-
#elif defined(_GNU_SOURCE)
115-
// GNU strerror_r returns char* (may or may not use buf)
116-
const char *result = strerror_r(err, buf, sizeof(buf));
117-
return result ? result : buf;
118141
#else
119-
// XSI-compliant strerror_r returns int
120-
strerror_r(err, buf, sizeof(buf));
121-
return buf;
142+
return strerrorRDispatch(strerror_r(err, buf, sizeof(buf)), buf);
122143
#endif
123144
}
124145

0 commit comments

Comments
 (0)