CatNiP prefinal
Sähköinen nuottikirja, HY-TKTKL-OHTUPROJ KESÄ11
/Users/awniemel/Notepad-SVN/svn/trunk/CatNiP/CatNiP/UncaughtExceptionHandler.m
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 #import "UncaughtExceptionHandler.h"
00014 #include <libkern/OSAtomic.h>
00015 #include <execinfo.h>
00016 
00017 NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
00018 NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
00019 NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
00020 
00021 volatile int32_t UncaughtExceptionCount = 0;
00022 const int32_t UncaughtExceptionMaximum = 10;
00023 
00024 const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
00025 const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
00026 
00027 @implementation UncaughtExceptionHandler
00028 
00029 + (NSArray *)backtrace
00030 {
00031          void* callstack[128];
00032          int frames = backtrace(callstack, 128);
00033          char **strs = backtrace_symbols(callstack, frames);
00034          
00035          int i;
00036          NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
00037          for (
00038                 i = UncaughtExceptionHandlerSkipAddressCount;
00039                 i < UncaughtExceptionHandlerSkipAddressCount +
00040                         UncaughtExceptionHandlerReportAddressCount;
00041                 i++)
00042          {
00043                 [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
00044          }
00045          free(strs);
00046          
00047          return backtrace;
00048 }
00049 
00050 - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
00051 {
00052         if (anIndex == 0)
00053         {
00054                 dismissed = YES;
00055         }
00056 }
00057 
00058 - (void)validateAndSaveCriticalApplicationData
00059 {
00060         
00061 }
00062 
00063 - (void)handleException:(NSException *)exception
00064 {
00065         [self validateAndSaveCriticalApplicationData];
00066         
00067         UIAlertView *alert =
00068                 [[[UIAlertView alloc]
00069                         initWithTitle:NSLocalizedString(@"Unhandled exception", nil)
00070                         message:[NSString stringWithFormat:NSLocalizedString(
00071                                 @"You can try to continue but the application may be unstable.\n\n"
00072                                 @"Debug details follow:\n%@\n%@", nil),
00073                                 [exception reason],
00074                                 [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]
00075                         delegate:self
00076                         cancelButtonTitle:NSLocalizedString(@"Quit", nil)
00077                         otherButtonTitles:NSLocalizedString(@"Continue", nil), nil]
00078                 autorelease];
00079         [alert show];
00080         
00081         CFRunLoopRef runLoop = CFRunLoopGetCurrent();
00082         CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
00083         
00084         while (!dismissed)
00085         {
00086                 for (NSString *mode in (NSArray *)allModes)
00087                 {
00088                         CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
00089                 }
00090         }
00091         
00092         CFRelease(allModes);
00093 
00094         NSSetUncaughtExceptionHandler(NULL);
00095         signal(SIGABRT, SIG_DFL);
00096         signal(SIGILL, SIG_DFL);
00097         signal(SIGSEGV, SIG_DFL);
00098         signal(SIGFPE, SIG_DFL);
00099         signal(SIGBUS, SIG_DFL);
00100         signal(SIGPIPE, SIG_DFL);
00101         
00102         if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName])
00103         {
00104                 kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
00105         }
00106         else
00107         {
00108                 [exception raise];
00109         }
00110 }
00111 
00112 @end
00113 
00114 void HandleException(NSException *exception)
00115 {
00116         int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
00117         if (exceptionCount > UncaughtExceptionMaximum)
00118         {
00119                 return;
00120         }
00121         
00122         NSArray *callStack = [UncaughtExceptionHandler backtrace];
00123         NSMutableDictionary *userInfo =
00124                 [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
00125         [userInfo
00126                 setObject:callStack
00127                 forKey:UncaughtExceptionHandlerAddressesKey];
00128         
00129         [[[[UncaughtExceptionHandler alloc] init] autorelease]
00130                 performSelectorOnMainThread:@selector(handleException:)
00131                 withObject:
00132                         [NSException
00133                                 exceptionWithName:[exception name]
00134                                 reason:[exception reason]
00135                                 userInfo:userInfo]
00136                 waitUntilDone:YES];
00137 }
00138 
00139 void SignalHandler(int signal)
00140 {
00141         int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
00142         if (exceptionCount > UncaughtExceptionMaximum)
00143         {
00144                 return;
00145         }
00146         
00147         NSMutableDictionary *userInfo =
00148                 [NSMutableDictionary
00149                         dictionaryWithObject:[NSNumber numberWithInt:signal]
00150                         forKey:UncaughtExceptionHandlerSignalKey];
00151 
00152         NSArray *callStack = [UncaughtExceptionHandler backtrace];
00153         [userInfo
00154                 setObject:callStack
00155                 forKey:UncaughtExceptionHandlerAddressesKey];
00156         
00157         [[[[UncaughtExceptionHandler alloc] init] autorelease]
00158                 performSelectorOnMainThread:@selector(handleException:)
00159                 withObject:
00160                         [NSException
00161                                 exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
00162                                 reason:
00163                                         [NSString stringWithFormat:
00164                                                 NSLocalizedString(@"Signal %d was raised.", nil),
00165                                                 signal]
00166                                 userInfo:
00167                                         [NSDictionary
00168                                                 dictionaryWithObject:[NSNumber numberWithInt:signal]
00169                                                 forKey:UncaughtExceptionHandlerSignalKey]]
00170                 waitUntilDone:YES];
00171 }
00172 
00173 void InstallUncaughtExceptionHandler()
00174 {
00175         NSSetUncaughtExceptionHandler(&HandleException);
00176         signal(SIGABRT, SignalHandler);
00177         signal(SIGILL, SignalHandler);
00178         signal(SIGSEGV, SignalHandler);
00179         signal(SIGFPE, SignalHandler);
00180         signal(SIGBUS, SignalHandler);
00181         signal(SIGPIPE, SignalHandler);
00182 }
00183 
 All Classes Files Functions Variables Enumerations Enumerator Properties Defines