summaryrefslogtreecommitdiffstats
path: root/src/polyp
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2006-05-22 15:20:46 +0000
committerPierre Ossman <ossman@cendio.se>2006-05-22 15:20:46 +0000
commit4e3dc7ce68561c16254712d713b2ccd472b8afe7 (patch)
tree2b0494e14605f3f3e133765126eaee3c77c8b482 /src/polyp
parentbf09399d0e84c43fbae3d24b5c71dc8d85b62fe7 (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.c3
-rw-r--r--src/polyp/context.c7
-rw-r--r--src/polyp/error.c90
-rw-r--r--src/polyp/error.h6
-rw-r--r--src/polyp/mainloop-signal.c5
-rw-r--r--src/polyp/mainloop.c3
-rw-r--r--src/polyp/util.c4
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;