diff options
author | Martin Willi <martin@revosec.ch> | 2014-05-28 12:15:10 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2014-06-04 15:53:00 +0200 |
commit | eb94f585954bf9f1ea0abc16e8d1413aaf265ac4 (patch) | |
tree | 78a651985fe7a1959afa72dfd137fdd10e906e5e | |
parent | 4189cd2f03d963c8ed31a21050201b2731eda4c5 (diff) | |
download | strongswan-eb94f585954bf9f1ea0abc16e8d1413aaf265ac4.tar.bz2 strongswan-eb94f585954bf9f1ea0abc16e8d1413aaf265ac4.tar.xz |
strerror: Don't directly depend on pthread
-rw-r--r-- | src/libstrongswan/utils/utils.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils/strerror.c | 122 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils/strerror.h | 10 |
3 files changed, 98 insertions, 36 deletions
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c index 81eb2acec..8ed0a25dd 100644 --- a/src/libstrongswan/utils/utils.c +++ b/src/libstrongswan/utils/utils.c @@ -55,6 +55,7 @@ void utils_init() #ifdef WIN32 windows_init(); #endif /* WIN32 */ + strerror_init(); } /** @@ -65,6 +66,7 @@ void utils_deinit() #ifdef WIN32 windows_deinit(); #endif /* WIN32 */ + strerror_deinit(); } /** diff --git a/src/libstrongswan/utils/utils/strerror.c b/src/libstrongswan/utils/utils/strerror.c index 95e463f5f..d35bbec68 100644 --- a/src/libstrongswan/utils/utils/strerror.c +++ b/src/libstrongswan/utils/utils/strerror.c @@ -15,7 +15,10 @@ #include <stdlib.h> #include <string.h> -#include <pthread.h> + +#include <library.h> +#include <threading/thread_value.h> +#include <threading/spinlock.h> #include "strerror.h" @@ -25,22 +28,16 @@ #define STRERROR_BUF_LEN 256 /** - * Key to store thread-specific error buffer - */ -static pthread_key_t strerror_buf_key; - -/** - * Only initialize the key above once + * Thread specific strerror buffer, as char* */ -static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT; +static thread_value_t *strerror_buf; +#ifndef HAVE_STRERROR_R /** - * Create the key used for the thread-specific error buffer + * Lock to access strerror() safely */ -static void create_strerror_buf_key() -{ - pthread_key_create(&strerror_buf_key, free); -} +static spinlock_t *strerror_lock; +#endif /* HAVE_STRERROR_R */ /** * Retrieve the error buffer assigned to the current thread (or create it) @@ -48,50 +45,103 @@ static void create_strerror_buf_key() static inline char *get_strerror_buf() { char *buf; + bool old = FALSE; - pthread_once(&strerror_buf_key_once, create_strerror_buf_key); - buf = pthread_getspecific(strerror_buf_key); + if (!strerror_buf) + { + return NULL; + } + + buf = strerror_buf->get(strerror_buf); if (!buf) { + if (lib->leak_detective) + { + old = lib->leak_detective->set_state(lib->leak_detective, FALSE); + } buf = malloc(STRERROR_BUF_LEN); - pthread_setspecific(strerror_buf_key, buf); + strerror_buf->set(strerror_buf, buf); + if (lib->leak_detective) + { + lib->leak_detective->set_state(lib->leak_detective, old); + } } return buf; } -#ifdef HAVE_STRERROR_R +/** + * Use real strerror() below + */ +#undef strerror + /* * Described in header. */ const char *strerror_safe(int errnum) { - char *buf = get_strerror_buf(), *msg; + char *buf, *msg; -#ifdef STRERROR_R_CHAR_P + buf = get_strerror_buf(); + if (!buf) + { + /* library not initialized? fallback */ + return strerror(errnum); + } +#ifdef HAVE_STRERROR_R +# ifdef STRERROR_R_CHAR_P /* char* version which may or may not return the original buffer */ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN); -#else +# else /* int version returns 0 on success */ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf; -#endif +# endif +#else /* HAVE_STRERROR_R */ + /* use a lock to ensure calling strerror(3) is thread-safe */ + strerror_lock->lock(strerror_lock); + msg = strncpy(buf, strerror(errnum), STRERROR_BUF_LEN); + strerror_lock->unlock(strerror_lock); + buf[STRERROR_BUF_LEN - 1] = '\0'; +#endif /* HAVE_STRERROR_R */ return msg; } -#else /* HAVE_STRERROR_R */ -/* we actually wan't to call strerror(3) below */ -#undef strerror -/* - * Described in header. + +/** + * free() with disabled leak detective */ -const char *strerror_safe(int errnum) +static void free_no_ld(void *buf) { - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - char *buf = get_strerror_buf(); + bool old = FALSE; - /* use a mutex to ensure calling strerror(3) is thread-safe */ - pthread_mutex_lock(&mutex); - strncpy(buf, strerror(errnum), STRERROR_BUF_LEN); - pthread_mutex_unlock(&mutex); - buf[STRERROR_BUF_LEN - 1] = '\0'; - return buf; + if (lib->leak_detective) + { + old = lib->leak_detective->set_state(lib->leak_detective, FALSE); + } + free(buf); + if (lib->leak_detective) + { + lib->leak_detective->set_state(lib->leak_detective, old); + } +} + +/** + * See header + */ +void strerror_init() +{ + strerror_buf = thread_value_create(free_no_ld); +#ifndef HAVE_STRERROR_R + strerror_lock = spinlock_create(); +#endif +} + +/** + * See header + */ +void strerror_deinit() +{ + strerror_buf->destroy(strerror_buf); + strerror_buf = NULL; +#ifndef HAVE_STRERROR_R + strerror_lock->destroy(strerror_lock); +#endif } -#endif /* HAVE_STRERROR_R */ diff --git a/src/libstrongswan/utils/utils/strerror.h b/src/libstrongswan/utils/utils/strerror.h index 2cb76f12e..e1b063842 100644 --- a/src/libstrongswan/utils/utils/strerror.h +++ b/src/libstrongswan/utils/utils/strerror.h @@ -33,6 +33,16 @@ const char *strerror_safe(int errnum); /** + * Initialize strerror_safe() + */ +void strerror_init(); + +/** + * Deinitialize strerror_safe() + */ +void strerror_deinit(); + +/** * Replace usages of strerror(3) with thread-safe variant. */ #define strerror(errnum) strerror_safe(errnum) |