From: oetiker Date: Fri, 6 Mar 2009 05:40:17 +0000 (+0000) Subject: Even though POSIX/XSI requires "strerror_r" to return an "int", some systems X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=5b4bfdb939a3047684d1fa4aa74a41542f9cdfb6;p=rrdtool-all.git Even though POSIX/XSI requires "strerror_r" to return an "int", some systems (e.g. the GNU libc) return a "char *" _and_ ignore the second argument (user provided buffer). The configure script now checks for that behavior using AC_FUNC_STRERROR_R. rrd_strerror() in rrd_thread_safe.c has been updated to (hopefully) handle all possible cases. Previously, rrd_strerror() would have returned "strerror_r failed. sorry!" in mostly any cases when using glibc, since "if (strerror_r())" had been used to check for errors which evaluates to true if a (non-NULL) pointer was returned. Now, we, at least, return the error number in case anything else fails. Thanks to Alessandro Iurlano for reporting this issue after spotting it in collectd . patch by Sebastian Harl git-svn-id: svn://svn.oetiker.ch/rrdtool/branches/1.3@1753 a5681a0c-68f1-0310-ab6d-d61299d08faa --- diff --git a/program/configure.ac b/program/configure.ac index 322b03b2..fba4862e 100644 --- a/program/configure.ac +++ b/program/configure.ac @@ -187,7 +187,9 @@ AC_C_BIGENDIAN dnl for each function found we get a definition in config.h dnl of the form HAVE_FUNCTION -AC_CHECK_FUNCS(tzset fsync mbstowcs opendir readdir chdir chroot getuid setlocale strerror strerror_r snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday) +AC_CHECK_FUNCS(tzset fsync mbstowcs opendir readdir chdir chroot getuid setlocale strerror snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday) + +AC_FUNC_STRERROR_R CONFIGURE_PART(Map/Fadvis/Madvise checking) diff --git a/program/src/rrd_thread_safe.c b/program/src/rrd_thread_safe.c index 14b89110..9aa4599e 100644 --- a/program/src/rrd_thread_safe.c +++ b/program/src/rrd_thread_safe.c @@ -59,11 +59,38 @@ const char *rrd_strerror( int err) { rrd_context_t *ctx = rrd_get_context(); + char *ret = "unknown error"; - if (strerror_r(err, ctx->lib_errstr, sizeof(ctx->lib_errstr))) - return "strerror_r failed. sorry!"; - else - return ctx->lib_errstr; + *ctx->lib_errstr = '\0'; + + /* Even though POSIX/XSI requires "strerror_r" to return an "int", some + * systems (e.g. the GNU libc) return a "char *" _and_ ignore the second + * argument ... -tokkee */ +#if STRERROR_R_CHAR_P + ret = strerror_r(err, ctx->lib_errstr, sizeof(ctx->lib_errstr)); + if ((! ret) || (*ret == '\0')) { + if (*ctx->lib_errstr != '\0') + ret = ctx->lib_errstr; + else { + /* according to the manpage this should not happen - + let's handle it somehow sanely anyway */ + snprintf(ctx->lib_errstr, sizeof(ctx->lib_errstr), + "unknown error %i - strerror_r did not return anything", + err); + ctx->lib_errstr[sizeof(ctx->lib_errstr) - 1] = '\0'; + ret = ctx->lib_errstr; + } + } +#else /* ! STRERROR_R_CHAR_P */ + if (strerror_r(err, ctx->lib_errstr, sizeof(ctx->lib_errstr))) { + snprintf(ctx->lib_errstr, sizeof(ctx->lib_errstr), + "unknown error %i - strerror_r returned with errno = %i", + err, errno); + ctx->lib_errstr[sizeof(ctx->lib_errstr) - 1] = '\0'; + } + ret = ctx->lib_errstr; +#endif + return ret; } #else #undef strerror