PageRenderTime 32ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/gecko_api/include/nsObjCExceptions.h

http://firefox-mac-pdf.googlecode.com/
C Header | 224 lines | 131 code | 36 blank | 57 comment | 6 complexity | db41a84f207b02949475bccf767af85c MD5 | raw file
  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
  4. *
  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/
  9. *
  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.
  14. *
  15. * The Original Code is mozilla.org code.
  16. *
  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.
  21. *
  22. * Contributor(s):
  23. * Josh Aas <josh@mozilla.com>
  24. * Robert O'Callahan <robert@ocallahan.org>
  25. *
  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.
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. #ifndef nsObjCExceptions_h_
  40. #define nsObjCExceptions_h_
  41. #import <Foundation/Foundation.h>
  42. #ifdef DEBUG
  43. #import <ExceptionHandling/NSExceptionHandler.h>
  44. #endif
  45. #include <unistd.h>
  46. #include <signal.h>
  47. #include "nsError.h"
  48. // See Mozilla bug 163260.
  49. // This file can only be included in an Objective-C context.
  50. static void nsObjCExceptionLog(NSException* aException)
  51. {
  52. NSLog(@"Mozilla has caught an Obj-C exception [%@: %@]",
  53. [aException name], [aException reason]);
  54. #ifdef DEBUG
  55. @try {
  56. // Try to get stack information out of the exception. 10.5 returns the stack
  57. // info with the callStackReturnAddresses selector.
  58. NSArray *stackTrace = nil;
  59. if ([aException respondsToSelector:@selector(callStackReturnAddresses)]) {
  60. NSArray* addresses = (NSArray*)
  61. [aException performSelector:@selector(callStackReturnAddresses)];
  62. if ([addresses count])
  63. stackTrace = addresses;
  64. }
  65. // 10.4 doesn't respond to callStackReturnAddresses so we'll try to pull the
  66. // stack info out of the userInfo. It might not be there, sadly :(
  67. if (!stackTrace)
  68. stackTrace = [[aException userInfo] objectForKey:NSStackTraceKey];
  69. if (stackTrace) {
  70. // The command line should look like this:
  71. // /usr/bin/atos -p <pid> -printHeader <stack frame addresses>
  72. NSMutableArray *args =
  73. [NSMutableArray arrayWithCapacity:[stackTrace count] + 3];
  74. [args addObject:@"-p"];
  75. int pid = [[NSProcessInfo processInfo] processIdentifier];
  76. [args addObject:[NSString stringWithFormat:@"%d", pid]];
  77. [args addObject:@"-printHeader"];
  78. unsigned int stackCount = [stackTrace count];
  79. unsigned int stackIndex = 0;
  80. for (; stackIndex < stackCount; stackIndex++)
  81. [args addObject:[[stackTrace objectAtIndex:stackIndex] stringValue]];
  82. NSPipe *outPipe = [NSPipe pipe];
  83. NSTask *task = [[NSTask alloc] init];
  84. [task setLaunchPath:@"/usr/bin/atos"];
  85. [task setArguments:args];
  86. [task setStandardOutput:outPipe];
  87. [task setStandardError:outPipe];
  88. NSLog(@"Generating stack trace for Obj-C exception...");
  89. // This will throw an exception if the atos tool cannot be found, and in
  90. // that case we'll just hit our @catch block below.
  91. [task launch];
  92. [task waitUntilExit];
  93. [task release];
  94. NSData *outData =
  95. [[outPipe fileHandleForReading] readDataToEndOfFile];
  96. NSString *outString =
  97. [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
  98. NSLog(@"Stack trace:\n%@", outString);
  99. [outString release];
  100. }
  101. else {
  102. NSLog(@"<No stack information available for Obj-C exception>");
  103. }
  104. }
  105. @catch (NSException *exn) {
  106. NSLog(@"Failed to generate stack trace for Obj-C exception [%@: %@]",
  107. [exn name], [exn reason]);
  108. }
  109. #endif
  110. }
  111. static void nsObjCExceptionAbort()
  112. {
  113. // We need to raise a mach-o signal here, the Mozilla crash reporter on
  114. // Mac OS X does not respond to POSIX signals. Raising mach-o signals directly
  115. // is tricky so we do it by just derefing a null pointer.
  116. int* foo = NULL;
  117. *foo = 1;
  118. }
  119. static void nsObjCExceptionLogAbort(NSException *e)
  120. {
  121. nsObjCExceptionLog(e);
  122. nsObjCExceptionAbort();
  123. }
  124. #define NS_OBJC_TRY(_e, _fail) \
  125. @try { _e; } \
  126. @catch(NSException *_exn) { \
  127. nsObjCExceptionLog(_exn); \
  128. _fail; \
  129. }
  130. #define NS_OBJC_TRY_EXPR(_e, _fail) \
  131. ({ \
  132. typeof(_e) _tmp; \
  133. @try { _tmp = (_e); } \
  134. @catch(NSException *_exn) { \
  135. nsObjCExceptionLog(_exn); \
  136. _fail; \
  137. } \
  138. _tmp; \
  139. })
  140. #define NS_OBJC_TRY_EXPR_NULL(_e) \
  141. NS_OBJC_TRY_EXPR(_e, 0)
  142. #define NS_OBJC_TRY_IGNORE(_e) \
  143. NS_OBJC_TRY(_e, )
  144. // To reduce code size the abort versions do not reuse above macros. This allows
  145. // catch blocks to only contain one call.
  146. #define NS_OBJC_TRY_ABORT(_e) \
  147. @try { _e; } \
  148. @catch(NSException *_exn) { \
  149. nsObjCExceptionLogAbort(_exn); \
  150. }
  151. #define NS_OBJC_TRY_EXPR_ABORT(_e) \
  152. ({ \
  153. typeof(_e) _tmp; \
  154. @try { _tmp = (_e); } \
  155. @catch(NSException *_exn) { \
  156. nsObjCExceptionLogAbort(_exn); \
  157. } \
  158. _tmp; \
  159. })
  160. // For wrapping blocks of Obj-C calls. Terminates app after logging.
  161. #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK @try {
  162. #define NS_OBJC_END_TRY_ABORT_BLOCK } @catch(NSException *_exn) { \
  163. nsObjCExceptionLogAbort(_exn); \
  164. }
  165. // Same as above ABORT_BLOCK but returns a value after the try/catch block to
  166. // suppress compiler warnings. This allows us to avoid having to refactor code
  167. // to get scoping right when wrapping an entire method.
  168. #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL @try {
  169. #define NS_OBJC_END_TRY_ABORT_BLOCK_NIL } @catch(NSException *_exn) { \
  170. nsObjCExceptionLogAbort(_exn); \
  171. } \
  172. return nil;
  173. #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL @try {
  174. #define NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL } @catch(NSException *_exn) { \
  175. nsObjCExceptionLogAbort(_exn); \
  176. } \
  177. return nsnull;
  178. #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT @try {
  179. #define NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT } @catch(NSException *_exn) { \
  180. nsObjCExceptionLogAbort(_exn);\
  181. } \
  182. return NS_ERROR_FAILURE;
  183. #define NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN @try {
  184. #define NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(_rv) } @catch(NSException *_exn) { \
  185. nsObjCExceptionLogAbort(_exn);\
  186. } \
  187. return _rv;
  188. #endif // nsObjCExceptions_h_