Skip to content

Commit ac436db

Browse files
authored
CDRIVER-4679 Prefer XSI-compliant strerror_r when available (#1350)
* CDRIVER-4679 Prefer XSI-compliant strerror_r when available * Use CheckCSourceCompiles to test for XSI-compliant strerror_r
1 parent df10571 commit ac436db

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ endif ()
394394
# Enable POSIX features up to POSIX.1-2008 plus the XSI extension and BSD-derived definitions.
395395
# Both _BSD_SOURCE and _DEFAULT_SOURCE are defined for backwards-compatibility with glibc 2.19 and earlier.
396396
# _BSD_SOURCE and _DEFAULT_SOURCE are required by `getpagesize`, `h_errno`, etc.
397-
# _XOPEN_SOURCE=700 is required by `strnlen`, etc.
397+
# _XOPEN_SOURCE=700 is required by `strnlen`, `strerror_r`, etc.
398398
add_definitions (-D_XOPEN_SOURCE=700 -D_BSD_SOURCE -D_DEFAULT_SOURCE)
399399
list (APPEND CMAKE_REQUIRED_DEFINITIONS -D_XOPEN_SOURCE=700 -D_BSD_SOURCE -D_DEFAULT_SOURCE)
400400

src/libbson/CMakeLists.txt

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ include (MongoC-Warnings)
1414

1515
set (BSON_OUTPUT_BASENAME "bson" CACHE STRING "Output bson library base name")
1616

17+
include (CheckCSourceCompiles)
1718
include (CheckFunctionExists)
1819
include (CheckIncludeFile)
20+
include (CheckIncludeFiles)
1921
include (CheckStructHasMember)
2022
include (CheckSymbolExists)
21-
include (TestBigEndian)
2223
include (InstallRequiredSystemLibraries)
24+
include (TestBigEndian)
2325

2426
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/build/cmake)
2527

@@ -83,8 +85,6 @@ else ()
8385
set (BSON_OS 1)
8486
endif ()
8587

86-
include (CheckIncludeFiles)
87-
8888
CHECK_INCLUDE_FILE (strings.h BSON_HAVE_STRINGS_H)
8989
if (NOT BSON_HAVE_STRINGS_H)
9090
set (BSON_HAVE_STRINGS_H 0)
@@ -119,6 +119,38 @@ else ()
119119
set (BSON_BYTE_ORDER 1234)
120120
endif ()
121121

122+
# 1. Normally, `defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600` should be enough
123+
# to detect if an XSI-compliant `strerror_r` is available.
124+
# 2. However, GNU provides an incompatible `strerror_r` as an extension,
125+
# requiring an additional test for `!defined(_GNU_SOURCE)`.
126+
# 3. However, musl does not support the GNU extension even when `_GNU_SOURCE` is
127+
# defined, preventing `!defined(_GNU_SOURCE)` from being a portable
128+
# XSI-compliance test.
129+
# 4. However, musl does not provide a feature test macro to detect compilation
130+
# with musl, and workarounds that use internal glibc feature test macros such
131+
# as `defined(__USE_GNU)` are explicitly forbidden by glibc documentation.
132+
# 5. Therefore, give up on using feature test macros: use `CheckCSourceCompiles`
133+
# to test if the current `strerror_r` is XSI-compliant if present.
134+
if (NOT WIN32)
135+
CHECK_C_SOURCE_COMPILES(
136+
[[
137+
#include <string.h>
138+
int test(int errnum, char *buf, size_t buflen) {
139+
return strerror_r (errnum, buf, buflen);
140+
}
141+
int main(void) {}
142+
]]
143+
BSON_HAVE_XSI_STRERROR_R
144+
FAIL_REGEX "int-conversion"
145+
)
146+
endif ()
147+
148+
if (BSON_HAVE_XSI_STRERROR_R)
149+
set(BSON_HAVE_XSI_STRERROR_R 1)
150+
else()
151+
set(BSON_HAVE_XSI_STRERROR_R 0)
152+
endif ()
153+
122154
configure_file (
123155
"${PROJECT_SOURCE_DIR}/src/bson/bson-config.h.in"
124156
"${PROJECT_BINARY_DIR}/src/bson/bson-config.h"

src/libbson/src/bson/bson-config.h.in

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,13 @@
122122
# undef BSON_HAVE_STRLCPY
123123
#endif
124124

125+
126+
/*
127+
* Define to 1 if you have an XSI-compliant strerror_r on your platform.
128+
*/
129+
#define BSON_HAVE_XSI_STRERROR_R @BSON_HAVE_XSI_STRERROR_R@
130+
#if BSON_HAVE_XSI_STRERROR_R != 1
131+
# undef BSON_HAVE_XSI_STRERROR_R
132+
#endif
133+
125134
#endif /* BSON_CONFIG_H */

src/libbson/src/bson/bson-error.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,14 @@ bson_strerror_r (int err_code, /* IN */
109109
if (strerror_s (buf, buflen, err_code) != 0) {
110110
ret = buf;
111111
}
112-
#elif defined(__GNUC__) && defined(_GNU_SOURCE)
113-
ret = strerror_r (err_code, buf, buflen);
114-
#else /* XSI strerror_r */
112+
#elif defined(BSON_HAVE_XSI_STRERROR_R)
115113
if (strerror_r (err_code, buf, buflen) == 0) {
116114
ret = buf;
117115
}
116+
#elif defined(_GNU_SOURCE)
117+
ret = strerror_r (err_code, buf, buflen);
118+
#else
119+
#error "Unable to find a supported strerror_r candidate"
118120
#endif
119121

120122
if (!ret) {

0 commit comments

Comments
 (0)