diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index b12137810..75084415f 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -985,6 +985,7 @@ 79659E151A0AFFF800280978 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CODE_SIGN_IDENTITY = "Developer ID Application"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Developer ID Application"; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)"; @@ -994,6 +995,7 @@ 79659E161A0AFFF800280978 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CODE_SIGN_IDENTITY = "Developer ID Application"; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)"; }; diff --git a/Source/Bugsnag/BugsnagConfiguration.h b/Source/Bugsnag/BugsnagConfiguration.h index b42398079..1c44614fb 100644 --- a/Source/Bugsnag/BugsnagConfiguration.h +++ b/Source/Bugsnag/BugsnagConfiguration.h @@ -27,6 +27,7 @@ #import #import "BugsnagMetaData.h" +#import "KSCrashReportWriter.h" @class BugsnagBreadcrumbs; @@ -41,6 +42,7 @@ @property(nonatomic,readwrite,retain) BugsnagMetaData* metaData; @property(nonatomic,readwrite,retain) BugsnagMetaData* config; @property(nonatomic,readonly,strong) BugsnagBreadcrumbs* breadcrumbs; +@property(nonatomic) void (*onCrashHandler)(const KSCrashReportWriter* writer); @property(nonatomic) BOOL autoNotify; diff --git a/Source/Bugsnag/BugsnagNotifier.m b/Source/Bugsnag/BugsnagNotifier.m index 2889f39fc..597bb5b82 100644 --- a/Source/Bugsnag/BugsnagNotifier.m +++ b/Source/Bugsnag/BugsnagNotifier.m @@ -52,6 +52,8 @@ char *configJSON; // Contains notifier state, under "deviceState" and crash-specific information under "crash". char *stateJSON; + // User onCrash handler + void (*onCrash)(const KSCrashReportWriter* writer); }; static struct bugsnag_data_t g_bugsnag_data; @@ -72,6 +74,9 @@ void BSSerializeDataCrashHandler(const KSCrashReportWriter *writer) { if (g_bugsnag_data.stateJSON) { writer->addJSONElement(writer, "state", g_bugsnag_data.stateJSON); } + if (g_bugsnag_data.onCrash) { + g_bugsnag_data.onCrash(writer); + } } /** @@ -117,6 +122,7 @@ - (id) initWithConfiguration:(BugsnagConfiguration*) initConfiguration { [self metaDataChanged: self.configuration.metaData]; [self metaDataChanged: self.configuration.config]; [self metaDataChanged: self.state]; + g_bugsnag_data.onCrash = self.configuration.onCrashHandler; } return self; diff --git a/docs/Configuration.md b/docs/Configuration.md index 9287e7fdd..013019c86 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -67,6 +67,28 @@ config.apiKey = @"YOUR_API_KEY_HERE"; [Bugsnag startBugsnagWithConfiguration: config]; ``` +### `onCrashHandler` + +When a crash occurs in an application, information about the runtime state of +the application is collected and prepared to be sent to Bugsnag on the next +launch. The `onCrashHandler` hook allows you to execute additional code after +the crash report has been written. + +**NOTE:** All functions called from a signal handler must be +[asynchronous-safe](https://www.securecoding.cert.org/confluence/display/c/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers). +This excludes any Objective-C, in particular. + +```objective-c +void HandleCrashedThread(const KSCrashReportWriter *writer) { + // possibly serialize data, call another crash reporter +} + +// ... + +BugsnagConfiguration *config = [[BugsnagConfiguration alloc] init]; +config.onCrashHandler = &HandleCrashedThread; +``` + ### `releaseStage` In order to distinguish between errors that occur in different stages of the