Bug 452317 - FeedConverter.js: QueryInterface should throw NS_ERROR_NO_INTERFACE...
[wine-gecko.git] / xpcom / base / nsObjCExceptions.h
blobfe4d4214dfd8777d3d2e93ca2cc826a1c623a497
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2008
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Josh Aas <josh@mozilla.com>
24 * Robert O'Callahan <robert@ocallahan.org>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the NPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef nsObjCExceptions_h_
41 #define nsObjCExceptions_h_
43 #import <Foundation/Foundation.h>
45 #ifdef DEBUG
46 #import <ExceptionHandling/NSExceptionHandler.h>
47 #endif
49 #if defined(MOZ_CRASHREPORTER) && defined(__cplusplus)
50 #include "nsICrashReporter.h"
51 #include "nsCOMPtr.h"
52 #include "nsServiceManagerUtils.h"
53 #endif
55 #include <unistd.h>
56 #include <signal.h>
57 #include "nsError.h"
59 // See Mozilla bug 163260.
60 // This file can only be included in an Objective-C context.
62 static void nsObjCExceptionLog(NSException* aException)
64 NSLog(@"Mozilla has caught an Obj-C exception [%@: %@]",
65 [aException name], [aException reason]);
67 #if defined(MOZ_CRASHREPORTER) && defined(__cplusplus)
68 // Attach exception info to the crash report.
69 nsCOMPtr<nsICrashReporter> crashReporter =
70 do_GetService("@mozilla.org/toolkit/crash-reporter;1");
71 if (crashReporter)
72 crashReporter->AppendObjCExceptionInfoToAppNotes(static_cast<void*>(aException));
73 #endif
75 #ifdef DEBUG
76 @try {
77 // Try to get stack information out of the exception. 10.5 returns the stack
78 // info with the callStackReturnAddresses selector.
79 NSArray *stackTrace = nil;
80 if ([aException respondsToSelector:@selector(callStackReturnAddresses)]) {
81 NSArray* addresses = (NSArray*)
82 [aException performSelector:@selector(callStackReturnAddresses)];
83 if ([addresses count])
84 stackTrace = addresses;
87 // 10.4 doesn't respond to callStackReturnAddresses so we'll try to pull the
88 // stack info out of the userInfo. It might not be there, sadly :(
89 if (!stackTrace)
90 stackTrace = [[aException userInfo] objectForKey:NSStackTraceKey];
92 if (stackTrace) {
93 // The command line should look like this:
94 // /usr/bin/atos -p <pid> -printHeader <stack frame addresses>
95 NSMutableArray *args =
96 [NSMutableArray arrayWithCapacity:[stackTrace count] + 3];
98 [args addObject:@"-p"];
99 int pid = [[NSProcessInfo processInfo] processIdentifier];
100 [args addObject:[NSString stringWithFormat:@"%d", pid]];
102 [args addObject:@"-printHeader"];
104 unsigned int stackCount = [stackTrace count];
105 unsigned int stackIndex = 0;
106 for (; stackIndex < stackCount; stackIndex++)
107 [args addObject:[[stackTrace objectAtIndex:stackIndex] stringValue]];
109 NSPipe *outPipe = [NSPipe pipe];
111 NSTask *task = [[NSTask alloc] init];
112 [task setLaunchPath:@"/usr/bin/atos"];
113 [task setArguments:args];
114 [task setStandardOutput:outPipe];
115 [task setStandardError:outPipe];
117 NSLog(@"Generating stack trace for Obj-C exception...");
119 // This will throw an exception if the atos tool cannot be found, and in
120 // that case we'll just hit our @catch block below.
121 [task launch];
123 [task waitUntilExit];
124 [task release];
126 NSData *outData =
127 [[outPipe fileHandleForReading] readDataToEndOfFile];
128 NSString *outString =
129 [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
131 NSLog(@"Stack trace:\n%@", outString);
133 [outString release];
135 else {
136 NSLog(@"<No stack information available for Obj-C exception>");
139 @catch (NSException *exn) {
140 NSLog(@"Failed to generate stack trace for Obj-C exception [%@: %@]",
141 [exn name], [exn reason]);
143 #endif
146 static void nsObjCExceptionAbort()
148 // We need to raise a mach-o signal here, the Mozilla crash reporter on
149 // Mac OS X does not respond to POSIX signals. Raising mach-o signals directly
150 // is tricky so we do it by just derefing a null pointer.
151 int* foo = NULL;
152 *foo = 1;
155 static void nsObjCExceptionLogAbort(NSException *e)
157 nsObjCExceptionLog(e);
158 nsObjCExceptionAbort();
161 #define NS_OBJC_TRY(_e, _fail) \
162 @try { _e; } \
163 @catch(NSException *_exn) { \
164 nsObjCExceptionLog(_exn); \
165 _fail; \
168 #define NS_OBJC_TRY_EXPR(_e, _fail) \
169 ({ \
170 typeof(_e) _tmp; \
171 @try { _tmp = (_e); } \
172 @catch(NSException *_exn) { \
173 nsObjCExceptionLog(_exn); \
174 _fail; \
176 _tmp; \
179 #define NS_OBJC_TRY_EXPR_NULL(_e) \
180 NS_OBJC_TRY_EXPR(_e, 0)
182 #define NS_OBJC_TRY_IGNORE(_e) \
183 NS_OBJC_TRY(_e, )
185 // To reduce code size the abort versions do not reuse above macros. This allows
186 // catch blocks to only contain one call.
188 #define NS_OBJC_TRY_ABORT(_e) \
189 @try { _e; } \
190 @catch(NSException *_exn) { \
191 nsObjCExceptionLogAbort(_exn); \
194 #define NS_OBJC_TRY_EXPR_ABORT(_e) \
195 ({ \
196 typeof(_e) _tmp; \
197 @try { _tmp = (_e); } \
198 @catch(NSException *_exn) { \
199 nsObjCExceptionLogAbort(_exn); \
201 _tmp; \
204 // For wrapping blocks of Obj-C calls. Terminates app after logging.
205 #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK @try {
206 #define NS_OBJC_END_TRY_ABORT_BLOCK } @catch(NSException *_exn) { \
207 nsObjCExceptionLogAbort(_exn); \
210 // Same as above ABORT_BLOCK but returns a value after the try/catch block to
211 // suppress compiler warnings. This allows us to avoid having to refactor code
212 // to get scoping right when wrapping an entire method.
214 #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL @try {
215 #define NS_OBJC_END_TRY_ABORT_BLOCK_NIL } @catch(NSException *_exn) { \
216 nsObjCExceptionLogAbort(_exn); \
218 return nil;
220 #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL @try {
221 #define NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL } @catch(NSException *_exn) { \
222 nsObjCExceptionLogAbort(_exn); \
224 return nsnull;
226 #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT @try {
227 #define NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT } @catch(NSException *_exn) { \
228 nsObjCExceptionLogAbort(_exn);\
230 return NS_ERROR_FAILURE;
232 #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN @try {
233 #define NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(_rv) } @catch(NSException *_exn) { \
234 nsObjCExceptionLogAbort(_exn);\
236 return _rv;
238 #define NS_OBJC_BEGIN_TRY_LOGONLY_BLOCK @try {
239 #define NS_OBJC_END_TRY_LOGONLY_BLOCK } @catch(NSException *_exn) { \
240 nsObjCExceptionLog(_exn); \
243 #endif // nsObjCExceptions_h_