Commit fa3eb5b1 authored by Stiopa Koltsov's avatar Stiopa Koltsov Committed by Facebook Github Bot

folly/string: better strerror_r detection

Summary:
There are two variants of `strerror_r` function, one returns
`int`, and another returns `char*`. Selecting proper version using
preprocessor macros portably is extremely hard.

For example, on Android function signature depends on `__USE_GNU` and
`__ANDROID_API__` macros (https://git.io/fjBBE).

So we are using C++ overloading trick: we pass a pointer of
`strerror_r` to `invoke_strerror_r` function, and C++ compiler
selects proper function.

Reviewed By: yfeldblum

Differential Revision: D15484722

fbshipit-source-id: fc0bd45fa67dc401631ffc185c9fad231e4a48a0
parent 03078807
......@@ -191,18 +191,6 @@ check_cxx_source_compiles("
FOLLY_USE_LIBSTDCPP
)
check_cxx_source_runs("
#include <string.h>
#include <errno.h>
int main(int argc, char** argv) {
char buf[1024];
buf[0] = 0;
int ret = strerror_r(ENOMEM, buf, sizeof(buf));
return ret;
}"
FOLLY_HAVE_XSI_STRERROR_R
)
check_cxx_source_runs("
#include <stdarg.h>
#include <stdio.h>
......
......@@ -61,7 +61,6 @@
#cmakedefine FOLLY_HAVE_WCHAR_SUPPORT 1
#cmakedefine FOLLY_HAVE_EXTRANDOM_SFMT19937 1
#cmakedefine FOLLY_USE_LIBCPP 1
#cmakedefine FOLLY_HAVE_XSI_STRERROR_R 1
#cmakedefine HAVE_VSNPRINTF_ERRORS 1
#cmakedefine FOLLY_USE_SYMBOLIZER 1
......
......@@ -460,6 +460,45 @@ std::string hexDump(const void* ptr, size_t size) {
return os.str();
}
// There are two variants of `strerror_r` function, one returns
// `int`, and another returns `char*`. Selecting proper version using
// preprocessor macros portably is extremely hard.
//
// For example, on Android function signature depends on `__USE_GNU` and
// `__ANDROID_API__` macros (https://git.io/fjBBE).
//
// So we are using C++ overloading trick: we pass a pointer of
// `strerror_r` to `invoke_strerror_r` function, and C++ compiler
// selects proper function.
FOLLY_MAYBE_UNUSED
static fbstring invoke_strerror_r(
int (*strerror_r)(int, char*, size_t),
int err,
char* buf,
size_t buflen) {
// Using XSI-compatible strerror_r
int r = strerror_r(err, buf, buflen);
// OSX/FreeBSD use EINVAL and Linux uses -1 so just check for non-zero
if (r != 0) {
return to<fbstring>(
"Unknown error ", err, " (strerror_r failed with error ", errno, ")");
} else {
return buf;
}
}
FOLLY_MAYBE_UNUSED
static fbstring invoke_strerror_r(
char* (*strerror_r)(int, char*, size_t),
int err,
char* buf,
size_t buflen) {
// Using GNU strerror_r
return strerror_r(err, buf, buflen);
}
fbstring errnoStr(int err) {
int savedErrno = errno;
......@@ -484,21 +523,9 @@ fbstring errnoStr(int err) {
} else {
result.assign(buf);
}
#elif FOLLY_HAVE_XSI_STRERROR_R || defined(__APPLE__)
// Using XSI-compatible strerror_r
int r = strerror_r(err, buf, sizeof(buf));
// OSX/FreeBSD use EINVAL and Linux uses -1 so just check for non-zero
if (r != 0) {
result = to<fbstring>(
"Unknown error ", err, " (strerror_r failed with error ", errno, ")");
} else {
result.assign(buf);
}
#else
// Using GNU strerror_r
result.assign(strerror_r(err, buf, sizeof(buf)));
// Using any strerror_r
result.assign(invoke_strerror_r(strerror_r, err, buf, sizeof(buf)));
#endif
return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment