From cdfca4d330c5fc8eb2ced74dbfec63cbda361185 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Thu, 19 Dec 2013 15:36:31 +0100 Subject: [PATCH] Add the option to define callbacks that will be executed prior to program termination after a crash has occurred This is _NOT_recommended to be used! Code that runs in such callbacks need to be async-safe, which excludes ANY Objective-C code and lots of C as well. See https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html --- Classes/BITCrashManager.h | 26 ++++++++++++++++++++++++++ Classes/BITCrashManager.m | 13 +++++++++++++ Classes/BITCrashManagerPrivate.h | 2 -- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Classes/BITCrashManager.h b/Classes/BITCrashManager.h index 5e61e1b92a..b3dc982639 100644 --- a/Classes/BITCrashManager.h +++ b/Classes/BITCrashManager.h @@ -32,6 +32,7 @@ #import "BITHockeyBaseManager.h" +#import /** * Crash Manager status @@ -160,6 +161,31 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) { @property (nonatomic, assign, getter=isMachExceptionHandlerEnabled) BOOL enableMachExceptionHandler; +/** + * Set the callbacks that will be executed prior to program termination after a crash has occurred + * + * PLCrashReporter provides support for executing an application specified function in the context + * of the crash reporter's signal handler, after the crash report has been written to disk. + * + * Writing code intended for execution inside of a signal handler is exceptionally difficult, and is _NOT_ recommended! + * + * _Program Flow and Signal Handlers_ + * + * When the signal handler is called the normal flow of the program is interrupted, and your program is an unknown state. Locks may be held, the heap may be corrupt (or in the process of being updated), and your signal handler may invoke a function that was being executed at the time of the signal. This may result in deadlocks, data corruption, and program termination. + * + * _Async-Safe Functions_ + * + * A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the CERT programming guide - SIG30-C, see https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers + * + * Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal handler. + * + * Documentation taken from PLCrashReporter: https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html + * + * @param callbacks A pointer to an initialized PLCrashReporterCallback structure, see https://www.plcrashreporter.org/documentation/api/v1.2-rc2/struct_p_l_crash_reporter_callbacks.html + */ +- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks; + + /** Flag that determines if an "Always" option should be shown diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index 9f518f0a5e..b76978cf64 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -72,6 +72,8 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus"; NSString *_analyzerInProgressFile; NSFileManager *_fileManager; + PLCrashReporterCallbacks *_crashCallBacks; + BOOL _crashIdenticalCurrentVersion; NSMutableData *_responseData; @@ -95,6 +97,7 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus"; _plCrashReporter = nil; _exceptionHandler = nil; + _crashCallBacks = nil; _crashIdenticalCurrentVersion = YES; _urlConnection = nil; @@ -385,6 +388,11 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus"; #pragma mark - Public + +- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks { + _crashCallBacks = callbacks; +} + /** * Check if the debugger is attached * @@ -702,6 +710,11 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus"; // can't break this NSError *error = NULL; + // set any user defined callbacks, hopefully the users knows what they do + if (_crashCallBacks) { + [self.plCrashReporter setCrashCallbacks:_crashCallBacks]; + } + // Enable the Crash Reporter if (![self.plCrashReporter enableCrashReporterAndReturnError: &error]) NSLog(@"[HockeySDK] WARNING: Could not enable crash reporter: %@", [error localizedDescription]); diff --git a/Classes/BITCrashManagerPrivate.h b/Classes/BITCrashManagerPrivate.h index dfc471156a..f1963926a0 100644 --- a/Classes/BITCrashManagerPrivate.h +++ b/Classes/BITCrashManagerPrivate.h @@ -31,8 +31,6 @@ #if HOCKEYSDK_FEATURE_CRASH_REPORTER -#import - @interface BITCrashManager () { }