将这个放在
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);
sigaction (Signal.SIGBUS, IntPtr.Zero, sigbus);
sigaction (Signal.SIGSEGV, IntPtr.Zero, sigsegv);
EnableCrashReportingUnsafe ();
sigaction (Signal.SIGBUS, sigbus, IntPtr.Zero);
sigaction (Signal.SIGSEGV, sigsegv, IntPtr.Zero);
Marshal.FreeHGlobal (sigbus);
Marshal.FreeHGlobal (sigsegv);
}
static void EnableCrashReportingUnsafe ()
{
var manager = BITHockeyManager.SharedHockeyManager;
manager.Configure (HockeyAppId, null);
manager.StartManager ();
}
在
FinishedLaunching
方法的开头调用
EnableCrashReporting()
。
如果需要,可以将此调用包装在
#if !DEBUG
指令中。
它是如何工作的?
我遵循了Rolf的建议:
一个可能的解决方案是允许mono处理所有的SIGSEGV信号(从技术上讲,崩溃报告库应该不处理SIGSEGV信号,或者它应该链接到mono的处理程序并且不进行任何自身处理)。如果mono确定SIGSEGV信号不是来自托管代码(也就是说发生了非常糟糕的事情),它将引发SIGABORT信号(崩溃报告库应该已经处理并将其视为崩溃)。正如您所理解的,这是必须在崩溃报告库中完成的事情。
还有Landon Fuller的Objective C实现:
#import <signal.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
struct sigaction sigbus_action, sigsegv_action;
sigaction(SIGBUS, NULL, &sigbus_action);
sigaction(SIGSEGV, NULL, &sigsegv_action);
sigaction(SIGBUS, &sigbus_action, NULL);
sigaction(SIGSEGV, &sigsegv_action, NULL);
return YES;
}
我使用
Banshee源代码作为如何从MonoTouch调用
sigaction
的参考点。希望能有所帮助!