]> code.delx.au - pulseaudio/blob - src/pulsecore/core-error.c
* more s/pulseaudio/PulseAudio/ replacements
[pulseaudio] / src / pulsecore / core-error.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #ifdef HAVE_PTHREAD
32 #include <pthread.h>
33 #endif
34
35 #ifdef HAVE_WINDOWS_H
36 #include <windows.h>
37 #endif
38
39 #include <pulse/utf8.h>
40 #include <pulse/xmalloc.h>
41
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/native-common.h>
44
45 #include "core-error.h"
46
47 #ifdef HAVE_PTHREAD
48
49 static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT;
50 static pthread_key_t tlsstr_key;
51
52 static void inittls(void) {
53 int ret;
54
55 ret = pthread_key_create(&tlsstr_key, pa_xfree);
56 if (ret) {
57 fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno);
58 exit(-1);
59 }
60 }
61
62 #elif HAVE_WINDOWS_H
63
64 static DWORD tlsstr_key = TLS_OUT_OF_INDEXES;
65 static DWORD monitor_key = TLS_OUT_OF_INDEXES;
66
67 static void inittls(void) {
68 HANDLE mutex;
69 char name[64];
70
71 sprintf(name, "pulse%d", (int)GetCurrentProcessId());
72
73 mutex = CreateMutex(NULL, FALSE, name);
74 if (!mutex) {
75 fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError());
76 exit(-1);
77 }
78
79 WaitForSingleObject(mutex, INFINITE);
80
81 if (tlsstr_key == TLS_OUT_OF_INDEXES) {
82 tlsstr_key = TlsAlloc();
83 monitor_key = TlsAlloc();
84 if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) {
85 fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError());
86 exit(-1);
87 }
88 }
89
90 ReleaseMutex(mutex);
91
92 CloseHandle(mutex);
93 }
94
95 /*
96 * This is incredibly brain dead, but this is necessary when dealing with
97 * the hell that is Win32.
98 */
99 struct monitor_data {
100 HANDLE thread;
101 void *data;
102 };
103
104 static DWORD WINAPI monitor_thread(LPVOID param) {
105 struct monitor_data *data;
106
107 data = (struct monitor_data*)param;
108 assert(data);
109
110 WaitForSingleObject(data->thread, INFINITE);
111
112 CloseHandle(data->thread);
113 pa_xfree(data->data);
114 pa_xfree(data);
115
116 return 0;
117 }
118
119 static void start_monitor(void) {
120 HANDLE thread;
121 struct monitor_data *data;
122
123 data = pa_xnew(struct monitor_data, 1);
124 assert(data);
125
126 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
127 GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS);
128
129 thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL);
130 assert(thread);
131
132 TlsSetValue(monitor_key, data);
133
134 CloseHandle(thread);
135 }
136
137 #else
138
139 /* Unsafe, but we have no choice */
140 static char *tlsstr;
141
142 #endif
143
144 const char* pa_cstrerror(int errnum) {
145 const char *origbuf;
146
147 #ifdef HAVE_STRERROR_R
148 char errbuf[128];
149 #endif
150
151 #ifdef HAVE_PTHREAD
152 char *tlsstr;
153
154 pthread_once(&cstrerror_once, inittls);
155
156 tlsstr = pthread_getspecific(tlsstr_key);
157 #elif defined(HAVE_WINDOWS_H)
158 char *tlsstr;
159 struct monitor_data *data;
160
161 inittls();
162
163 tlsstr = TlsGetValue(tlsstr_key);
164 if (!tlsstr)
165 start_monitor();
166 data = TlsGetValue(monitor_key);
167 #endif
168
169 if (tlsstr)
170 pa_xfree(tlsstr);
171
172 #ifdef HAVE_STRERROR_R
173
174 #ifdef __GLIBC__
175 origbuf = strerror_r(errnum, errbuf, sizeof(errbuf));
176 if (origbuf == NULL)
177 origbuf = "";
178 #else
179 if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) {
180 origbuf = errbuf;
181 errbuf[sizeof(errbuf) - 1] = '\0';
182 } else
183 origbuf = "";
184 #endif
185
186 #else
187 /* This might not be thread safe, but we hope for the best */
188 origbuf = strerror(errnum);
189 #endif
190
191 tlsstr = pa_locale_to_utf8(origbuf);
192 if (!tlsstr) {
193 fprintf(stderr, "Unable to convert, filtering\n");
194 tlsstr = pa_utf8_filter(origbuf);
195 }
196
197 #ifdef HAVE_PTHREAD
198 pthread_setspecific(tlsstr_key, tlsstr);
199 #elif defined(HAVE_WINDOWS_H)
200 TlsSetValue(tlsstr_key, tlsstr);
201 data->data = tlsstr;
202 #endif
203
204 return tlsstr;
205 }