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