Problems with detection of strerror_r
hishamhm opened this issue · 3 comments
In my system (Linux, GCC 6.2.0, Glibc 2.24), the latest compat-5.3.c
is failing to build:
lua-compat-5.3/compat-5.3.c:36:47: error: operator '!' has no right operand
(!defined(_GNU_SOURCE) || !_GNU_SOURCE)
^
My app defines _GNU_SOURCE with #define _GNU_SOURCE
with no value, as usual.
Changing that line into (!defined(_GNU_SOURCE))
, however, produces this compile-time warning:
In file included from lua-compat-5.3/compat-5.3.h:415:0,
from lua-compat-5.3/compat-5.3.c:7:
lua-compat-5.3/compat-5.3.c: In function ‘compat53_strerror’:
lua-compat-5.3/compat-5.3.c:85:10: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
return strerror_r(en, buff, sz);
^~~~~~~~~~
lua-compat-5.3/compat-5.3.c:85:10: warning: return makes pointer from integer without a cast [-Wint-conversion]
return strerror_r(en, buff, sz);
^~~~~~~~~~~~~~~~~~~~~~~~
I don't get the warning if I force the defines to use the XSI version:
#define COMPAT53_HAVE_STRERROR_R_XSI 1
#define COMPAT53_HAVE_STRERROR_R_GNU 0
Something borked in my setup as well, maybe?
Looks like https://github.com/keplerproject/lua-compat-5.3/blob/9cb6834fe07297ba79e7453978cf7e7d8d8c339a/c-api/compat-5.3.c#L36 should be change to just !defined(_GNU_SOURCE)
First, it should be !defined(_GNU_SOURCE)
. At least that's what the official headers use apparently (even though the manpage claims (_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE
), probably to avoid this exact issue.
Second, we have another problem: It seems that we don't have a reliable way to detect whether we have the GNU version or the POSIX version of strerror_r
. Checking the same preprocessor symbols might not do it, because those can change between inclusion of string.h
and our tests.
At the moment I'm considering something like the following when a glibc is used:
char buffer[255] = { 0 }; /* zero initialized */
int myerrno = errno;
strerror_r(myerrno, buffer, sizeof(buffer)); /* use either version of strerror_r */
if (buffer[0] != '\0')
return buffer; /* strerror_r wrote into our buffer */
else
/* buffer is unchanged, so we probably have GNU strerror_r which returned a
* static constant string. Chances are that strerror will return the same static
* constant string and therefore be thread-safe. */
return strerror(myerrno);
When I find time I'll take a look at the glibc sources to make sure that the last assumption at least holds for the current glibc version.
I'm open to other suggestions.