Mercurial > sdl-ios-xcode
annotate src/SDL_error.c @ 1176:dd2a8deeb26d
Date: Mon, 17 Oct 2005 20:09:03 -0400
From: Mark Schreiber <mark7@alumni.cmu.edu>
To: ryan@clutteredmind.org
Subject: [PATCH]SDL mprotect() crash fix
(I'm going to throw this patch your way at the suggestion of #SDL --
for some reason, I had some difficulty sending it to the main list
last time, and I go bonkers subscribing to send each email or
patch...)
Currently, when I run SDL applications as non-root using
SDL_VIDEODRIVER=dga, the fbdev fallback mprotect()s read/write the
proper size of mmapped /dev/fb0 (7.5MB), but on framebuffer release
mprotect()s read-only the range by the entire size of my video memory
(128MB), which causes a segfault:
#0 0x002a9a27 in ?? () from /lib/libc.so.6
#1 0x04a63eb6 in SDL_XDGAUnmapFramebuffer (screen=3D0) at XF86DGA2.c:978
#2 0x04a63efc in SDL_XDGACloseFramebuffer (dpy=3D0x9d3f008, screen=3D0)
at XF86DGA2.c:268
#3 0x04a68b57 in DGA_Available () at SDL_dgavideo.c:98
#4 0x04a53677 in SDL_VideoInit (driver_name=3D0xbfb0bfc7 "dga", flags=3D0)
at SDL_video.c:180
#5 0x04a2613f in SDL_InitSubSystem (flags=3D32) at SDL.c:74
#6 0x04a2617c in SDL_Init (flags=3D32) at SDL.c:166
#7 0x08049722 in main (argc=3D1, argv=3D0x0) at testwin.c:32
This is SDL 1.2.8 on Fedora Core 4, radeon driver for a Radeon 9250,
xorg-x11-6.8.2-37.
I've attached a one-line patch against SDL CVS that updates the size
of the framebuffer at framebuffer map time so that the mprotect() on
unmap will be the same size. I'm not sure if this is the best
approach (i.e. one might want to retain the original value), but it
does make my SDL applications work without segfaulting.
-- Best of luck, Mark Schreiber
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 19 Nov 2005 18:57:00 +0000 |
parents | f69f4d25fb20 |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
1
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Simple error handling in SDL */ | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <stdarg.h> | |
33 #include <string.h> | |
34 | |
35 #include "SDL_types.h" | |
36 #include "SDL_getenv.h" | |
37 #include "SDL_error.h" | |
38 #include "SDL_error_c.h" | |
39 #ifndef DISABLE_THREADS | |
40 #include "SDL_thread_c.h" | |
41 #endif | |
42 | |
43 #ifdef DISABLE_THREADS | |
44 /* The default (non-thread-safe) global error variable */ | |
45 static SDL_error SDL_global_error; | |
46 | |
47 #define SDL_GetErrBuf() (&SDL_global_error) | |
48 #endif /* DISABLE_THREADS */ | |
49 | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
50 #ifdef __CYGWIN__ |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
51 #define DISABLE_STDIO |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
52 #endif |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
53 |
0 | 54 #define SDL_ERRBUFIZE 1024 |
55 | |
56 /* Private functions */ | |
57 | |
58 static void SDL_LookupString(const Uint8 *key, Uint16 *buf, int buflen) | |
59 { | |
60 /* FIXME: Add code to lookup key in language string hash-table */ | |
61 | |
62 /* Key not found in language string hash-table */ | |
63 while ( *key && (--buflen > 0) ) { | |
64 *buf++ = *key++; | |
65 } | |
66 *buf = 0; /* NULL terminate string */ | |
67 } | |
68 | |
69 /* Public functions */ | |
70 | |
71 void SDL_SetError (const char *fmt, ...) | |
72 { | |
73 va_list ap; | |
74 SDL_error *error; | |
75 | |
76 /* Copy in the key, mark error as valid */ | |
77 error = SDL_GetErrBuf(); | |
78 error->error = 1; | |
79 strncpy((char *)error->key, fmt, sizeof(error->key)); | |
80 error->key[sizeof(error->key)-1] = '\0'; | |
81 | |
82 va_start(ap, fmt); | |
83 error->argc = 0; | |
84 while ( *fmt ) { | |
85 if ( *fmt++ == '%' ) { | |
86 switch (*fmt++) { | |
87 case 0: /* Malformed format string.. */ | |
88 --fmt; | |
89 break; | |
90 #if 0 /* What is a character anyway? (UNICODE issues) */ | |
91 case 'c': | |
92 error->args[error->argc++].value_c = | |
93 va_arg(ap, unsigned char); | |
94 break; | |
95 #endif | |
96 case 'd': | |
97 error->args[error->argc++].value_i = | |
98 va_arg(ap, int); | |
99 break; | |
100 case 'f': | |
101 error->args[error->argc++].value_f = | |
102 va_arg(ap, double); | |
103 break; | |
104 case 'p': | |
105 error->args[error->argc++].value_ptr = | |
106 va_arg(ap, void *); | |
107 break; | |
108 case 's': | |
109 { | |
110 int index = error->argc; | |
1172
f69f4d25fb20
Don't crash if a NULL is passed for a "%s" parameter to SDL_SetError(),
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
111 char *str = va_arg(ap, char *); |
f69f4d25fb20
Don't crash if a NULL is passed for a "%s" parameter to SDL_SetError(),
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
112 if (str == NULL) |
f69f4d25fb20
Don't crash if a NULL is passed for a "%s" parameter to SDL_SetError(),
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
113 str = "(null)"; |
f69f4d25fb20
Don't crash if a NULL is passed for a "%s" parameter to SDL_SetError(),
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
114 strncpy((char *)error->args[index].buf, str, ERR_MAX_STRLEN); |
0 | 115 error->args[index].buf[ERR_MAX_STRLEN-1] = 0; |
116 error->argc++; | |
117 } | |
118 break; | |
119 default: | |
120 break; | |
121 } | |
122 if ( error->argc >= ERR_MAX_ARGS ) { | |
123 break; | |
124 } | |
125 } | |
126 } | |
127 va_end(ap); | |
128 | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
129 #ifndef DISABLE_STDIO |
0 | 130 /* If we are in debug mode, print out an error message */ |
131 #ifdef DEBUG_ERROR | |
132 fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError()); | |
133 #else | |
134 if ( getenv("SDL_DEBUG") ) { | |
135 fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError()); | |
136 } | |
137 #endif | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
138 #endif /* !DISABLE_STDIO */ |
0 | 139 } |
140 | |
141 /* Print out an integer value to a UNICODE buffer */ | |
142 static int PrintInt(Uint16 *str, unsigned int maxlen, int value) | |
143 { | |
144 char tmp[128]; | |
145 int len, i; | |
146 | |
147 sprintf(tmp, "%d", value); | |
148 len = 0; | |
149 if ( strlen(tmp) < maxlen ) { | |
150 for ( i=0; tmp[i]; ++i ) { | |
151 *str++ = tmp[i]; | |
152 ++len; | |
153 } | |
154 } | |
155 return(len); | |
156 } | |
157 /* Print out a double value to a UNICODE buffer */ | |
158 static int PrintDouble(Uint16 *str, unsigned int maxlen, double value) | |
159 { | |
160 char tmp[128]; | |
161 int len, i; | |
162 | |
163 sprintf(tmp, "%f", value); | |
164 len = 0; | |
165 if ( strlen(tmp) < maxlen ) { | |
166 for ( i=0; tmp[i]; ++i ) { | |
167 *str++ = tmp[i]; | |
168 ++len; | |
169 } | |
170 } | |
171 return(len); | |
172 } | |
173 /* Print out a pointer value to a UNICODE buffer */ | |
174 static int PrintPointer(Uint16 *str, unsigned int maxlen, void *value) | |
175 { | |
176 char tmp[128]; | |
177 int len, i; | |
178 | |
179 sprintf(tmp, "%p", value); | |
180 len = 0; | |
181 if ( strlen(tmp) < maxlen ) { | |
182 for ( i=0; tmp[i]; ++i ) { | |
183 *str++ = tmp[i]; | |
184 ++len; | |
185 } | |
186 } | |
187 return(len); | |
188 } | |
189 | |
190 /* This function has a bit more overhead than most error functions | |
191 so that it supports internationalization and thread-safe errors. | |
192 */ | |
193 Uint16 *SDL_GetErrorMsgUNICODE(Uint16 *errstr, unsigned int maxlen) | |
194 { | |
195 SDL_error *error; | |
196 | |
197 /* Clear the error string */ | |
198 *errstr = 0; --maxlen; | |
199 | |
200 /* Get the thread-safe error, and print it out */ | |
201 error = SDL_GetErrBuf(); | |
202 if ( error->error ) { | |
203 Uint16 translated[ERR_MAX_STRLEN], *fmt, *msg; | |
204 int len; | |
205 int argi; | |
206 | |
207 /* Print out the UNICODE error message */ | |
208 SDL_LookupString(error->key, translated, sizeof(translated)); | |
209 msg = errstr; | |
210 argi = 0; | |
211 for ( fmt=translated; *fmt && (maxlen > 0); ) { | |
212 if ( *fmt == '%' ) { | |
213 switch (fmt[1]) { | |
214 case 'S': /* Special SKIP operand */ | |
215 argi += (fmt[2] - '0'); | |
216 ++fmt; | |
217 break; | |
218 case '%': | |
219 *msg++ = '%'; | |
220 maxlen -= 1; | |
221 break; | |
222 #if 0 /* What is a character anyway? (UNICODE issues) */ | |
223 case 'c': | |
224 *msg++ = (unsigned char) | |
225 error->args[argi++].value_c; | |
226 maxlen -= 1; | |
227 break; | |
228 #endif | |
229 case 'd': | |
230 len = PrintInt(msg, maxlen, | |
231 error->args[argi++].value_i); | |
232 msg += len; | |
233 maxlen -= len; | |
234 break; | |
235 case 'f': | |
236 len = PrintDouble(msg, maxlen, | |
237 error->args[argi++].value_f); | |
238 msg += len; | |
239 maxlen -= len; | |
240 break; | |
241 case 'p': | |
242 len = PrintPointer(msg, maxlen, | |
243 error->args[argi++].value_ptr); | |
244 msg += len; | |
245 maxlen -= len; | |
246 break; | |
247 case 's': /* UNICODE string */ | |
248 { Uint16 buf[ERR_MAX_STRLEN], *str; | |
249 SDL_LookupString(error->args[argi++].buf, buf, sizeof(buf)); | |
250 str = buf; | |
251 while ( *str && (maxlen > 0) ) { | |
252 *msg++ = *str++; | |
253 maxlen -= 1; | |
254 } | |
255 } | |
256 break; | |
257 } | |
258 fmt += 2; | |
259 } else { | |
260 *msg++ = *fmt++; | |
261 maxlen -= 1; | |
262 } | |
263 } | |
264 *msg = 0; /* NULL terminate the string */ | |
265 } | |
266 return(errstr); | |
267 } | |
268 | |
269 Uint8 *SDL_GetErrorMsg(Uint8 *errstr, unsigned int maxlen) | |
270 { | |
271 Uint16 *errstr16; | |
272 unsigned int i; | |
273 | |
274 /* Allocate the UNICODE buffer */ | |
275 errstr16 = (Uint16 *)malloc(maxlen * (sizeof *errstr16)); | |
276 if ( ! errstr16 ) { | |
277 strncpy((char *)errstr, "Out of memory", maxlen); | |
278 errstr[maxlen-1] = '\0'; | |
279 return(errstr); | |
280 } | |
281 | |
282 /* Get the error message */ | |
283 SDL_GetErrorMsgUNICODE(errstr16, maxlen); | |
284 | |
285 /* Convert from UNICODE to Latin1 encoding */ | |
286 for ( i=0; i<maxlen; ++i ) { | |
287 errstr[i] = (Uint8)errstr16[i]; | |
288 } | |
289 | |
290 /* Free UNICODE buffer (if necessary) */ | |
291 free(errstr16); | |
292 | |
293 return(errstr); | |
294 } | |
295 | |
296 /* Available for backwards compatibility */ | |
297 char *SDL_GetError (void) | |
298 { | |
299 static char errmsg[SDL_ERRBUFIZE]; | |
300 | |
301 return((char *)SDL_GetErrorMsg((unsigned char *)errmsg, SDL_ERRBUFIZE)); | |
302 } | |
303 | |
304 void SDL_ClearError(void) | |
305 { | |
306 SDL_error *error; | |
307 | |
308 error = SDL_GetErrBuf(); | |
309 error->error = 0; | |
310 } | |
311 | |
312 /* Very common errors go here */ | |
313 void SDL_Error(SDL_errorcode code) | |
314 { | |
315 switch (code) { | |
316 case SDL_ENOMEM: | |
317 SDL_SetError("Out of memory"); | |
318 break; | |
319 case SDL_EFREAD: | |
320 SDL_SetError("Error reading from datastream"); | |
321 break; | |
322 case SDL_EFWRITE: | |
323 SDL_SetError("Error writing to datastream"); | |
324 break; | |
325 case SDL_EFSEEK: | |
326 SDL_SetError("Error seeking in datastream"); | |
327 break; | |
328 default: | |
329 SDL_SetError("Unknown SDL error"); | |
330 break; | |
331 } | |
332 } | |
333 | |
334 #ifdef TEST_ERROR | |
335 int main(int argc, char *argv[]) | |
336 { | |
337 char buffer[BUFSIZ+1]; | |
338 | |
339 SDL_SetError("Hi there!"); | |
340 printf("Error 1: %s\n", SDL_GetError()); | |
341 SDL_ClearError(); | |
342 memset(buffer, '1', BUFSIZ); | |
343 buffer[BUFSIZ] = 0; | |
344 SDL_SetError("This is the error: %s (%f)", buffer, 1.0); | |
345 printf("Error 2: %s\n", SDL_GetError()); | |
346 exit(0); | |
347 } | |
348 #endif |