From: Ben Pfaff Date: Wed, 19 Jun 2013 22:44:54 +0000 (-0700) Subject: New function ovs_strerror() as a thread-safe replacement for strerror(). X-Git-Tag: sliver-openvswitch-1.10.90-3~6^2~1 X-Git-Url: http://git.onelab.eu/?p=sliver-openvswitch.git;a=commitdiff_plain;h=5fcbed7479c5f1d2cc08c3f544f10dbbe8ec0d90 New function ovs_strerror() as a thread-safe replacement for strerror(). Signed-off-by: Ben Pfaff --- diff --git a/configure.ac b/configure.ac index 78ac593af..e4f999153 100644 --- a/configure.ac +++ b/configure.ac @@ -45,6 +45,7 @@ AC_SEARCH_LIBS([pow], [m]) AC_SEARCH_LIBS([clock_gettime], [rt]) AC_SEARCH_LIBS([timer_create], [rt]) AC_SEARCH_LIBS([pthread_sigmask], [pthread]) +AC_FUNC_STRERROR_R OVS_CHECK_ESX OVS_CHECK_COVERAGE diff --git a/lib/util.c b/lib/util.c index 29157d31b..1bb5096b0 100644 --- a/lib/util.c +++ b/lib/util.c @@ -18,6 +18,7 @@ #include "util.h" #include #include +#include #include #include #include @@ -44,6 +45,9 @@ const char *subprogram_name = ""; /* --version option output. */ static char *program_version; +/* Buffer used by ovs_strerror(). */ +DEFINE_PER_THREAD_DATA(struct { char s[128]; }, strerror_buffer, { "" }); + void ovs_assert_failure(const char *where, const char *function, const char *condition) @@ -306,19 +310,41 @@ ovs_error_valist(int err_no, const char *format, va_list args) const char * ovs_retval_to_string(int retval) { - static char unknown[48]; + return (!retval ? "" + : retval == EOF ? "End of file" + : ovs_strerror(retval)); +} - if (!retval) { - return ""; - } - if (retval > 0) { - return strerror(retval); - } - if (retval == EOF) { - return "End of file"; +const char * +ovs_strerror(int error) +{ + enum { BUFSIZE = sizeof strerror_buffer_get()->s }; + int save_errno; + char *buffer; + char *s; + + save_errno = errno; + buffer = strerror_buffer_get()->s; + +#if STRERROR_R_CHAR_P + /* GNU style strerror_r() might return an immutable static string, or it + * might write and return 'buffer', but in either case we can pass the + * returned string directly to the caller. */ + s = strerror_r(error, buffer, BUFSIZE); +#else /* strerror_r() returns an int. */ + s = buffer; + if (strerror_r(error, buffer, BUFSIZE)) { + /* strerror_r() is only allowed to fail on ERANGE (because the buffer + * is too short). We don't check the actual failure reason because + * POSIX requires strerror_r() to return the error but old glibc + * (before 2.13) returns -1 and sets errno. */ + snprintf(buffer, BUFSIZE, "Unknown error %d", error); } - snprintf(unknown, sizeof unknown, "***unknown return value: %d***", retval); - return unknown; +#endif + + errno = save_errno; + + return s; } /* Sets global "program_name" and "program_version" variables. Should diff --git a/lib/util.h b/lib/util.h index c436a437a..c71f027c5 100644 --- a/lib/util.h +++ b/lib/util.h @@ -214,6 +214,7 @@ void ovs_error(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3); void ovs_error_valist(int err_no, const char *format, va_list) PRINTF_FORMAT(2, 0); const char *ovs_retval_to_string(int); +const char *ovs_strerror(int); void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii); bool str_to_int(const char *, int base, int *);