I'm using PLCrashReporter in my iOS project and I'm curious, is it possible to use Core Foundation code in my custom crash callback. The thing, that handle my needs is CFPreferences.Here is part of code, that I create:
void LMCrashCallback(siginfo_t* info, ucontext_t* uap, void* context) {
CFStringRef networkStatusOnCrash;
networkStatusOnCrash = (CFStringRef)CFPreferencesCopyAppValue(networkStatusKey, kCFPreferencesCurrentApplication);
CFStringRef additionalInfo = CFStringCreateWithFormat(
NULL, NULL, CFSTR( "Additional Crash Properties:[Internet: %@]", networkStatusOnCrash);
CFPreferencesSetAppValue(additionalInfoKey, additionalInfo,
kCFPreferencesCurrentApplication);
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
}
My target is to collect some system information, just in time when app crashed, e.g Internet connection type.
I know it is not good idea to create own crash callback due to async-safe functions, but this can help.
Also as other option: Is there a way to extend somehow PLCrashReportSystemInfo class?
This is very dangerous. In particular the call to
CFStringCreateWithFormat
allocates memory. Allocating memory in the middle of a crash handler can lead to battery-draining deadlock (yep; had that bug…) For example, if you were in the middle offree()
(which is not an uncommon place to crash), you may already be holding a spinlock on the heap. When you callmalloc
to get some memory, you may spinlock the heap again and deadlock in a tight-loop. The heap needs to be locked so often and for such short periods of time that it doesn't use a blocking lock. It does the equivalent ofwhile (locked) {}
.You seem to just be reading a preference and copying it to another preference. There's no reason to do that inside a crash handler. Just check
hasPendingCrashReport
during startup (which I assume you're doing already), and read the key then. It's not clear whatnetworkStatusKey
is, but it should still be there when you start up again.If for any reason it's modified very early (before you call
hasPendingCrashReport
), you can grab it inmain()
before launching the app. Or you can grab it in a+load
method, which is called even earlier.