]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-errors.m
objc4-493.11.tar.gz
[apple/objc4.git] / runtime / objc-errors.m
1 /*
2 * Copyright (c) 1999-2003, 2005-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * objc-errors.m
25 * Copyright 1988-2001, NeXT Software, Inc., Apple Computer, Inc.
26 */
27
28 #include "objc-private.h"
29
30 #if TARGET_OS_WIN32
31
32 #include <conio.h>
33
34 PRIVATE_EXTERN void _objc_inform_on_crash(const char *fmt, ...)
35 {
36 }
37
38 PRIVATE_EXTERN void _objc_inform(const char *fmt, ...)
39 {
40 va_list args;
41 va_start(args, fmt);
42 _vcprintf(fmt, args);
43 va_end(args);
44 _cprintf("\n");
45 }
46
47 PRIVATE_EXTERN void _objc_fatal(const char *fmt, ...)
48 {
49 va_list args;
50 va_start(args, fmt);
51 _vcprintf(fmt, args);
52 va_end(args);
53 _cprintf("\n");
54
55 abort();
56 }
57
58 PRIVATE_EXTERN void __objc_error(id rcv, const char *fmt, ...)
59 {
60 va_list args;
61 va_start(args, fmt);
62 _vcprintf(fmt, args);
63 va_end(args);
64
65 abort();
66 }
67
68 PRIVATE_EXTERN void _objc_error(id rcv, const char *fmt, va_list args)
69 {
70 _vcprintf(fmt, args);
71
72 abort();
73 }
74
75 #else
76
77
78 OBJC_EXPORT void (*_error)(id, const char *, va_list);
79
80 static void _objc_trap(void) __attribute__((noreturn));
81
82 // Add "message" to any forthcoming crash log.
83 static void _objc_crashlog(const char *message)
84 {
85 char *newmsg;
86
87 #if 0
88 {
89 // for debugging at BOOT time.
90 extern char **_NSGetProgname(void);
91 FILE *crashlog = fopen("/_objc_crash.log", "a");
92 setbuf(crashlog, NULL);
93 fprintf(crashlog, "[%s] %s\n", *_NSGetProgname(), message);
94 fclose(crashlog);
95 sync();
96 }
97 #endif
98
99 static mutex_t crashlog_lock = MUTEX_INITIALIZER;
100 mutex_lock(&crashlog_lock);
101
102 char *oldmsg = (char *)CRGetCrashLogMessage();
103
104 if (!oldmsg) {
105 newmsg = strdup(message);
106 } else {
107 asprintf(&newmsg, "%s\n%s", oldmsg, message);
108 }
109
110 if (newmsg) {
111 // Strip trailing newline
112 char *c = &newmsg[strlen(newmsg)-1];
113 if (*c == '\n') *c = '\0';
114
115 if (oldmsg) free(oldmsg);
116 CRSetCrashLogMessage(newmsg);
117 }
118
119 mutex_unlock(&crashlog_lock);
120 }
121
122 // Print "message" to the console.
123 static void _objc_syslog(const char *message)
124 {
125 if (fcntl(STDERR_FILENO, F_GETFL, 0) != -1) {
126 // stderr is open - use it
127 write(STDERR_FILENO, message, strlen(message));
128 if (message[strlen(message)-1] != '\n') {
129 write(STDERR_FILENO, "\n", 1);
130 }
131 } else {
132 syslog(LOG_ERR, "%s", message);
133 }
134 }
135
136 /*
137 * _objc_error is the default *_error handler.
138 */
139 #if __OBJC2__
140 PRIVATE_EXTERN __attribute__((noreturn))
141 #else
142 // used by ExceptionHandling.framework
143 #endif
144 void _objc_error(id self, const char *fmt, va_list ap)
145 {
146 char *buf1;
147 char *buf2;
148
149 vasprintf(&buf1, fmt, ap);
150 asprintf(&buf2, "objc[%d]: %s: %s\n",
151 getpid(), object_getClassName(self), buf1);
152 _objc_syslog(buf2);
153 _objc_crashlog(buf2);
154
155 _objc_trap();
156 }
157
158 /*
159 * this routine handles errors that involve an object (or class).
160 */
161 PRIVATE_EXTERN void __objc_error(id rcv, const char *fmt, ...)
162 {
163 va_list vp;
164
165 va_start(vp,fmt);
166 #if !__OBJC2__
167 (*_error)(rcv, fmt, vp);
168 #endif
169 _objc_error (rcv, fmt, vp); /* In case (*_error)() returns. */
170 va_end(vp);
171 }
172
173 /*
174 * this routine handles severe runtime errors...like not being able
175 * to read the mach headers, allocate space, etc...very uncommon.
176 */
177 PRIVATE_EXTERN void _objc_fatal(const char *fmt, ...)
178 {
179 va_list ap;
180 char *buf1;
181 char *buf2;
182
183 va_start(ap,fmt);
184 vasprintf(&buf1, fmt, ap);
185 va_end (ap);
186
187 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
188 _objc_syslog(buf2);
189 _objc_crashlog(buf2);
190
191 _objc_trap();
192 }
193
194 /*
195 * this routine handles soft runtime errors...like not being able
196 * add a category to a class (because it wasn't linked in).
197 */
198 PRIVATE_EXTERN void _objc_inform(const char *fmt, ...)
199 {
200 va_list ap;
201 char *buf1;
202 char *buf2;
203
204 va_start (ap,fmt);
205 vasprintf(&buf1, fmt, ap);
206 va_end (ap);
207
208 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
209 _objc_syslog(buf2);
210
211 free(buf2);
212 free(buf1);
213 }
214
215
216 /*
217 * Like _objc_inform(), but prints the message only in any
218 * forthcoming crash log, not to the console.
219 */
220 PRIVATE_EXTERN void _objc_inform_on_crash(const char *fmt, ...)
221 {
222 va_list ap;
223 char *buf1;
224 char *buf2;
225
226 va_start (ap,fmt);
227 vasprintf(&buf1, fmt, ap);
228 va_end (ap);
229
230 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
231 _objc_crashlog(buf2);
232
233 free(buf2);
234 free(buf1);
235 }
236
237
238 /*
239 * Like calling both _objc_inform and _objc_inform_on_crash.
240 */
241 PRIVATE_EXTERN void _objc_inform_now_and_on_crash(const char *fmt, ...)
242 {
243 va_list ap;
244 char *buf1;
245 char *buf2;
246
247 va_start (ap,fmt);
248 vasprintf(&buf1, fmt, ap);
249 va_end (ap);
250
251 asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
252 _objc_crashlog(buf2);
253 _objc_syslog(buf2);
254
255 free(buf2);
256 free(buf1);
257 }
258
259
260 /* Kill the process in a way that generates a crash log.
261 * This is better than calling exit(). */
262 static void _objc_trap(void)
263 {
264 __builtin_trap();
265 }
266
267 /* Try to keep _objc_warn_deprecated out of crash logs
268 * caused by _objc_trap(). rdar://4546883 */
269 __attribute__((used))
270 static void _objc_trap2(void)
271 {
272 __builtin_trap();
273 }
274
275 #endif
276
277
278 BREAKPOINT_FUNCTION(
279 void _objc_warn_deprecated(void)
280 );
281
282 PRIVATE_EXTERN void _objc_inform_deprecated(const char *oldf, const char *newf)
283 {
284 if (PrintDeprecation) {
285 if (newf) {
286 _objc_inform("The function %s is obsolete. Use %s instead. Set a breakpoint on _objc_warn_deprecated to find the culprit.", oldf, newf);
287 } else {
288 _objc_inform("The function %s is obsolete. Do not use it. Set a breakpoint on _objc_warn_deprecated to find the culprit.", oldf);
289 }
290 }
291 _objc_warn_deprecated();
292 }