From 8bcf3b4fb858a838e5a623ec417a93540fa43f2b Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Tue, 14 Aug 2012 14:11:44 +0200 Subject: [PATCH] FreeSWITCH: Add switch_strerror_r() to fix problems with XSI and GNU variants of strerror_r(). GNU variant of strerror_r() returns char *, while the XSI version returns int. To make things worse, glibc ships both and added a unused result warning in recent versions (2.16) causing the build to fail. Add our own custom wrapper that always returns a pointer to the message buffer and additionally make XSI versions of strerror_r() GNU compatible by returning "Unknown error xxx" if no error message is available. Fixes: src/switch_rtp.c: In function 'rtp_common_read': src/switch_rtp.c:3313:15: error: ignoring return value of 'strerror_r', declared with attribute warn_unused_result [-Werror=unused-result] cc1: all warnings being treated as errors Signed-off-by: Stefan Knoblich --- configure.in | 7 +++++++ src/include/switch_utils.h | 10 ++++++++++ src/switch_rtp.c | 4 ++-- src/switch_utils.c | 25 +++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 0345dd208c..87d868b7a0 100644 --- a/configure.in +++ b/configure.in @@ -495,6 +495,13 @@ AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs time AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups]) AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp]) +# Check availability and return type of strerror_r +# (NOTE: apr-1-config sets -D_GNU_SOURCE at build-time, need to run the check with it too) +save_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" +AC_FUNC_STRERROR_R +CPPFLAGS="$save_CPPFLAGS" + AX_HAVE_CPU_SET AC_CHECK_LIB(rt, clock_gettime, [AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if you have clock_gettime()])]) diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 40560a0434..6b1824a153 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -837,6 +837,16 @@ SWITCH_DECLARE(char *) switch_format_number(const char *num); SWITCH_DECLARE(unsigned int) switch_atoui(const char *nptr); SWITCH_DECLARE(unsigned long) switch_atoul(const char *nptr); +/** + * Portable version of strerror_r(), work around for the incompatible + * return type of GNU and XSI variants. + * \param[in] errnum Error number + * \param[both] buf Buffer for error message + * \param[in] buflen Size of message buffer + * \return Pointer to message buffer, returning error message or "Unknown error xxx" if none found + */ +SWITCH_DECLARE(char *) switch_strerror_r(int errnum, char *buf, switch_size_t buflen); + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/switch_rtp.c b/src/switch_rtp.c index f0749d8087..1c23efc714 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -3310,8 +3310,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (!SWITCH_STATUS_IS_BREAK(poll_status) && poll_status != SWITCH_STATUS_TIMEOUT) { char tmp[128] = ""; - strerror_r(poll_status, tmp, sizeof(tmp)); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Poll failed with error: %d [%s]\n", poll_status, tmp); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Poll failed with error: %d [%s]\n", + poll_status, switch_strerror_r(poll_status, tmp, sizeof(tmp))); ret = -1; goto end; } diff --git a/src/switch_utils.c b/src/switch_utils.c index 157ce177f2..b0c4e1a287 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -2968,6 +2968,31 @@ SWITCH_DECLARE(unsigned long) switch_atoul(const char *nptr) else return (unsigned long) tmp; } + +SWITCH_DECLARE(char *) switch_strerror_r(int errnum, char *buf, switch_size_t buflen) +{ +#ifdef HAVE_STRERROR_R +#ifdef STRERROR_R_CHAR_P + /* GNU variant returning char *, avoids warn-unused-result error */ + return strerror_r(errnum, buf, buflen); +#else + /* + * XSI variant returning int, with GNU compatible error string, + * if no message could be found + */ + if (strerror_r(errnum, buf, buflen)) { + switch_snprintf(buf, buflen, "Unknown error %d", errnum); + } + return buf; +#endif /* STRERROR_R_CHAR_P */ +#else + /* Fallback, copy string into private buffer */ + switch_copy_string(buf, strerror(errnum), buflen); + return buf; +#endif +} + + /* For Emacs: * Local Variables: * mode:c