diff options
author | Pierre Ossman <ossman@cendio.se> | 2006-05-22 15:20:46 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2006-05-22 15:20:46 +0000 |
commit | 4e3dc7ce68561c16254712d713b2ccd472b8afe7 (patch) | |
tree | 2b0494e14605f3f3e133765126eaee3c77c8b482 /src/polyp | |
parent | bf09399d0e84c43fbae3d24b5c71dc8d85b62fe7 (diff) |
Wrap strerror() in a function that makes it thread safe and converts the
output to UTF-8.
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@945 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/polyp')
-rw-r--r-- | src/polyp/client-conf.c | 3 | ||||
-rw-r--r-- | src/polyp/context.c | 7 | ||||
-rw-r--r-- | src/polyp/error.c | 90 | ||||
-rw-r--r-- | src/polyp/error.h | 6 | ||||
-rw-r--r-- | src/polyp/mainloop-signal.c | 5 | ||||
-rw-r--r-- | src/polyp/mainloop.c | 3 | ||||
-rw-r--r-- | src/polyp/util.c | 4 |
7 files changed, 110 insertions, 8 deletions
diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 1ebcff43..0b3154c8 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -29,6 +29,7 @@ #include <errno.h> #include <string.h> +#include <polyp/error.h> #include <polyp/xmalloc.h> #include <polypcore/log.h> @@ -123,7 +124,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r"); if (!f && errno != EINTR) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } diff --git a/src/polyp/context.c b/src/polyp/context.c index a3b49d4b..eb563819 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -47,6 +47,7 @@ #include "../polypcore/winsock.h" +#include <polyp/error.h> #include <polyp/version.h> #include <polyp/xmalloc.h> @@ -440,7 +441,7 @@ static int context_connect_spawn(pa_context *c) { pa_context_ref(c); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log(__FILE__": socketpair() failed: %s", strerror(errno)); + pa_log(__FILE__": socketpair(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } @@ -454,7 +455,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.prefork(); if ((pid = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s", strerror(errno)); + pa_log(__FILE__": fork(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) @@ -510,7 +511,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.postfork(); if (r < 0) { - pa_log(__FILE__": waitpid() failed: %s", strerror(errno)); + pa_log(__FILE__": waitpid(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { diff --git a/src/polyp/error.c b/src/polyp/error.c index e78d072e..062b6f36 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -23,9 +23,23 @@ #include <config.h> #endif +#include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#ifdef HAVE_PTHREAD +#include <pthread.h> +#endif + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif + +#include <polyp/utf8.h> +#include <polyp/xmalloc.h> + +#include <polypcore/core-util.h> #include <polypcore/native-common.h> #include "error.h" @@ -58,3 +72,79 @@ const char*pa_strerror(int error) { return errortab[error]; } + +#ifdef HAVE_PTHREAD + +static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT; +static pthread_key_t tlsstr_key; + +static void inittls(void) { + int ret; + + ret = pthread_key_create(&tlsstr_key, pa_xfree); + if (ret) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno); + exit(-1); + } +} + +#elif HAVE_WINDOWS_H + +static __declspec(thread) char *tlsstr; + +#else + +/* Unsafe, but we have no choice */ +static char *tlsstr; + +#endif + +char* pa_cstrerror(int errnum) { + const char *origbuf; + +#ifdef HAVE_STRERROR_R + char errbuf[128]; +#endif + +#ifdef HAVE_PTHREAD + char *tlsstr; + + pthread_once(&cstrerror_once, inittls); + + tlsstr = pthread_getspecific(tlsstr_key); +#endif + + if (tlsstr) + pa_xfree(tlsstr); + +#ifdef HAVE_STRERROR_R + +#ifdef __GLIBC__ + origbuf = strerror_r(errnum, errbuf, sizeof(errbuf)); + if (origbuf == NULL) + origbuf = ""; +#else + if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) { + origbuf = errbuf; + errbuf[sizeof(errbuf) - 1] = '\0'; + } else + origbuf = ""; +#endif + +#else + /* This might not be thread safe, but we hope for the best */ + origbuf = strerror(errnum); +#endif + + tlsstr = pa_locale_to_utf8(origbuf); + if (!tlsstr) { + fprintf(stderr, "Unable to convert, filtering\n"); + tlsstr = pa_utf8_filter(origbuf); + } + +#ifdef HAVE_PTHREAD + pthread_setspecific(tlsstr_key, tlsstr); +#endif + + return tlsstr; +} diff --git a/src/polyp/error.h b/src/polyp/error.h index 9856c1af..33507bfd 100644 --- a/src/polyp/error.h +++ b/src/polyp/error.h @@ -33,6 +33,12 @@ PA_C_DECL_BEGIN /** Return a human readable error message for the specified numeric error code */ const char* pa_strerror(int error); +/** A wrapper around the standard strerror() function that converts the + * string to UTF-8. The function is thread safe but the returned string is + * only guaranteed to exist until the thread exits or pa_cstrerror() is + * called again from the same thread. */ +char* pa_cstrerror(int errnum); + PA_C_DECL_END #endif diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index c57437b6..c6ad431a 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -36,6 +36,7 @@ #include <windows.h> #endif +#include <polyp/error.h> #include <polyp/xmalloc.h> #include <polypcore/core-util.h> @@ -89,7 +90,7 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags if (errno == EAGAIN) return; - pa_log(__FILE__": read(): %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); return; } @@ -106,7 +107,7 @@ int pa_signal_init(pa_mainloop_api *a) { assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); if (pipe(signal_pipe) < 0) { - pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + pa_log(__FILE__": pipe(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 6b5b3b25..6088fa4b 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -44,6 +44,7 @@ #include "../polypcore/pipe.h" #endif +#include <polyp/error.h> #include <polyp/timeval.h> #include <polyp/xmalloc.h> @@ -689,7 +690,7 @@ int pa_mainloop_poll(pa_mainloop *m) { if (errno == EINTR) r = 0; else - pa_log(__FILE__": poll(): %s", strerror(errno)); + pa_log(__FILE__": poll(): %s", pa_cstrerror(errno)); } } diff --git a/src/polyp/util.c b/src/polyp/util.c index ed59a5c6..91054483 100644 --- a/src/polyp/util.c +++ b/src/polyp/util.c @@ -51,6 +51,8 @@ #include "../polypcore/winsock.h" +#include <polyp/error.h> + #include <polypcore/log.h> #include <polypcore/core-util.h> @@ -107,7 +109,7 @@ char *pa_get_user_name(char *s, size_t l) { char *pa_get_host_name(char *s, size_t l) { assert(s && l > 0); if (gethostname(s, l) < 0) { - pa_log(__FILE__": gethostname(): %s", strerror(errno)); + pa_log(__FILE__": gethostname(): %s", pa_cstrerror(errno)); return NULL; } s[l-1] = 0; |