appcenter-sdk-apple
appcenter-sdk-apple copied to clipboard
Equivalent method for setting BitCrashManagerCallbacks
Description
Using HockeyApp SDK for Mac, we had the option to set a callback method for doing additional (simple) tasks when the crash occurs, prior to program termination:
- (void)setCrashCallbacks: (BITCrashManagerCallbacks *) callbacks;
There's no similar option in the AppCenter SDK, will this be made available? Our app clears log files on app restart so it's too late to retrieve them by the time the MSCrashesDelegate starts.
Details
- Which SDK version are you using?
- 2.2.0
- Which OS version did you experience the issue on?
- OS X 10.14
- Which Cocoapods version are you using (run
pod --version
)?- manual
- What device version did you see this error on? Were you using an emulator or a physical device?
- Mac Mini
- What language are you using?
- [X ] Objective C
- [ ] Swift
Hey @hypherion2 - can you elaborate on your use case a bit more? What kind of tasks are you trying to accomplish? Thanks!
As I mentioned, we use it to save/backup the logs so we can include them in the crash report. They are automatically overwritten on next app restart, before we get notified that the app had previously crashed, so we can no longer include them with AppCenter crash reporting.
@winnieli1208 we also dump UIView & UIViewController hierarchy and general application state before process terminates. It is very useful for investigations of hard to reproduce cases.
Thanks for the additional context. It looks like a relatively small feature for our team to implement and I've added this to our roadmap. I don't have an exact target date at this moment but I will post here when I have a clearer timeline.
Thanks!
Another use-case: I'm using AVAudioRecorder
to record audio and the audio file becomes corrupt if the app crashes. However, if I would be able to call recorder.stop()
in a "setCrashCallbacks"-type callback, the recording would not be corrupt.
@sindresorhus you cannot safely call any Objective-C methods in the signal handler. Please read more about it (restrictions) in underlying library (that was used in HockeyApp too) docs: https://github.com/microsoft/plcrashreporter/blob/6b7ca9a2faad6ea990ff60b0a3ee4fdf3db59150/Source/CrashReporter.h#L205-L231
@MatkovIvan I'm ok with that. The recording is already corrupt without, so it cannot become worse.
As I understand, using AppCenterCrashes means using NSSetUncaughtExceptionHandler
is not possible since AppCenter sets up systems to catch all possible crashes. I also understand that there is no exposed callback/delegate-method that we could use to do a cleanup operation before the crashed app terminates, because the sources of the crash can be diverse, and the app can be in an unpredictable state.
However I would like to know if there is a way to still mitigate some of the crash scenarios. Are there hooks from AppCenter, or from AppKit, that can be called to try to run a last-minute cleanup after a crash? Again, I understand a catch-all method is not possible, but what can be done to try and catch some of these cases? I mentioned NSSetUncaughtExceptionHandler
above. Maybe there is a way to still set this callback up, and get some scenarios covered there?
Thanks a lot!
Note: my app is in Swift 5.
Hi @lwouis
Thank you for reaching out to us! You are right, there is no exposed callback or delegate calling when the crash is happened. And yes, It is not safe to execute a clean up code in a signal handler, as Ivan mentioned above.
However, if you are still interested in using the NSSetUncaughtExceptionHandler
in your app, what you can try do is to chain the handlers. First, start the AppCenter Crashes, then retrieve the handler set by AppCenter using NSGetUncaughtExceptionHandler
, save it locally, write your handler and call app center’s saved handler at the end of your handler. Then set your handler using NSSetUncaughtExceptionHandler
. This way you will handle the error in your app and then allow app center to handle it and send the crash the AppCenter portal. You can also try reverse the handler calls order. However if you do so, there is no guarantee that the app center handler will be executed correctly since it will depend on the code in your handler, so you can expect to potentially miss some crashes.
Please keep in mind that using NSSetUncaughtExceptionHandler
does not guarantee to handle all crashes, and its usage can lead to an unpredictable results.
Thanks @DmitriyKirakosyan for the pointers!
That strategy you described focuses on NSSetUncaughtExceptionHandler
, which to my understanding only catches objc exceptions. My question about a hook/callback from AppCenter Crashes was in hopes that I could cover more scenarios that one of my objc dependencies throwing.
Is there a way I could hijack something here in my objc class which extends NSApplication
?
@import Cocoa;
@import AppCenterCrashes;
#import "AppCenterApplication.h"
@implementation AppCenterApplication
- (void)reportException:(NSException*)exception {
[MSCrashes applicationDidReportException:exception];
[super reportException:exception];
}
- (void)sendEvent:(NSEvent*)theEvent {
@try {
[super sendEvent:theEvent];
} @catch (NSException* exception) {
[self reportException:exception];
}
}
@end
I want to run literally one function call before exiting. It's an OS API called CGSSetSymbolicHotKeyEnabled
. I expect it to be extremely short. Best case scenario, it gets called and users doesn't have any issue. Worst case scenario it doesn't get called, and we are back to the current situation. In that sense I feel hooking an attempt somewhere within AppCenter Crashes machinery would be a net benefit.
There's no public APIs for it. That is an existing feature request, but up until mid-2021 we mainly focus on reliability and improving performance : Roadmap
Internally some of this code already exists. Microsoft are using the post crash callback from PLCR for their own purposes (applying an interface shim) and have put in half of the code necessary to expose a second level callback to the user, in MSACCrashesPrivate.h
I exposed it for my own purposes at https://github.com/jbb1003/appcenter-sdk-apple/tree/feature/post_crash_callback - I keep a RAM log and dump it to store (with signal-safe code) in the event of a crash so I can add it as an attachment to a crash.
Obviously a crash could trample over the memory used for the log, or for storing the file path of the log, but in general it won't, and this approach has proved very useful in the past (when I was using HockeyApp).
UPDATE
I had a further look at how MS are using the PLCR post crash callback, and realised that MS are doing pretty much what I wanted to achieve (and the code has the same potential issues regarding memory trampling). If you log an Analytics event, and it has not been uploaded prior to a crash, it will be saved to file during the crash and then uploaded with the crash report. So there is no loss of data. This gets me enough of what I want that it's no longer worth me forking the SDK, but I will leave the code up there in case it's useful for anyone else.
As we do not have plans to add support for this feature in the next year, I'm closing the issue.