Put this in AppDelegate.cs
:
[DllImport ("libc")]
private static extern int sigaction (Signal sig, IntPtr act, IntPtr oact);
enum Signal {
SIGBUS = 10,
SIGSEGV = 11
}
static void EnableCrashReporting ()
{
IntPtr sigbus = Marshal.AllocHGlobal (512);
IntPtr sigsegv = Marshal.AllocHGlobal (512);
// Store Mono SIGSEGV and SIGBUS handlers
sigaction (Signal.SIGBUS, IntPtr.Zero, sigbus);
sigaction (Signal.SIGSEGV, IntPtr.Zero, sigsegv);
// Enable crash reporting libraries
EnableCrashReportingUnsafe ();
// Restore Mono SIGSEGV and SIGBUS handlers
sigaction (Signal.SIGBUS, sigbus, IntPtr.Zero);
sigaction (Signal.SIGSEGV, sigsegv, IntPtr.Zero);
Marshal.FreeHGlobal (sigbus);
Marshal.FreeHGlobal (sigsegv);
}
static void EnableCrashReportingUnsafe ()
{
// Run your crash reporting library initialization code here--
// this example uses HockeyApp but it should work well
// with TestFlight or other libraries.
// Verify in documentation that your library of choice
// installs its sigaction hooks before leaving this method.
var manager = BITHockeyManager.SharedHockeyManager;
manager.Configure (HockeyAppId, null);
manager.StartManager ();
}
Call EnableCrashReporting ()
in the beginning of FinishedLaunching
method.
Wrap this call in #if !DEBUG
directive if you want.
How does it work?
I followed Rolf's suggestion:
One possible solution is to allow mono to handle all SIGSEGV signals
(technically speaking the crash reporting lib should either not handle
the SIGSEGV signal, or it should chain to mono's handler and not do
any processing by itself). If mono determines that the SIGSEGV signal
is not from managed code (i.e. something very bad happened), it will
raise a SIGABORT signal (which the crash reporting lib should already
handle and treat as a crash). As you can understand this is something
that has to be done in the crash reporting library.
And Landon Fuller's Objective C implementation:
#import <signal.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/* Save Mono's signal handler actions */
struct sigaction sigbus_action, sigsegv_action;
sigaction(SIGBUS, NULL, &sigbus_action);
sigaction(SIGSEGV, NULL, &sigsegv_action);
// Enable the crash reporter here. Ie, [[PLCrashReporter sharedReporter] enableCrashReporterAndReturnError:],
// or whatever is the correct initialization mechanism for the crash reporting service you're using
/* Restore Mono's signal handlers */
sigaction(SIGBUS, &sigbus_action, NULL);
sigaction(SIGSEGV, &sigsegv_action, NULL);
return YES;
}
I used Banshee source code as a reference point for how to call sigaction
from MonoTouch.
Hope it helps!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…