CrashReporter.mm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #import "PLCrashReporter.h"
  2. #import "CrashReporter.h"
  3. extern NSString* GetCrashReportsPath();
  4. void CrashedCheckBelowForHintsWhy();
  5. static NSUncaughtExceptionHandler* gsCrashReporterUEHandler = NULL;
  6. static void SavePendingCrashReport()
  7. {
  8. if (![[UnityPLCrashReporter sharedReporter] hasPendingCrashReport])
  9. return;
  10. NSFileManager *fm = [NSFileManager defaultManager];
  11. NSError *error;
  12. if (![fm createDirectoryAtPath: GetCrashReportsPath() withIntermediateDirectories: YES attributes: nil error: &error])
  13. {
  14. ::printf("CrashReporter: could not create crash report directory: %s\n", [[error localizedDescription] UTF8String]);
  15. return;
  16. }
  17. NSData *data = [[UnityPLCrashReporter sharedReporter] loadPendingCrashReportDataAndReturnError: &error];
  18. if (data == nil)
  19. {
  20. ::printf("CrashReporter: failed to load crash report data: %s\n", [[error localizedDescription] UTF8String]);
  21. return;
  22. }
  23. NSString* file = [GetCrashReportsPath() stringByAppendingPathComponent: @"crash-"];
  24. unsigned long long seconds = (unsigned long long)[[NSDate date] timeIntervalSince1970];
  25. file = [file stringByAppendingString: [NSString stringWithFormat: @"%llu", seconds]];
  26. file = [file stringByAppendingString: @".plcrash"];
  27. if ([data writeToFile: file atomically: YES])
  28. {
  29. ::printf("CrashReporter: saved pending crash report.\n");
  30. if (![[UnityPLCrashReporter sharedReporter] purgePendingCrashReportAndReturnError: &error])
  31. {
  32. ::printf("CrashReporter: couldn't remove pending report: %s\n", [[error localizedDescription] UTF8String]);
  33. }
  34. }
  35. else
  36. {
  37. ::printf("CrashReporter: couldn't save crash report.\n");
  38. }
  39. }
  40. static void InitCrashReporter()
  41. {
  42. NSError *error;
  43. UnityInstallPostCrashCallback();
  44. if ([[UnityPLCrashReporter sharedReporter] enableCrashReporterAndReturnError: &error])
  45. ::printf("CrashReporter: initialized\n");
  46. else
  47. NSLog(@"CrashReporter: could not enable crash reporter: %@", error);
  48. SavePendingCrashReport();
  49. }
  50. static void UncaughtExceptionHandler(NSException *exception)
  51. {
  52. NSLog(@"Uncaught exception: %@: %@\n%@", [exception name], [exception reason], [exception callStackSymbols]);
  53. if (gsCrashReporterUEHandler)
  54. gsCrashReporterUEHandler(exception);
  55. }
  56. static void InitObjCUEHandler()
  57. {
  58. // Crash reporter sets its own handler, so we have to save it and call it manually
  59. gsCrashReporterUEHandler = NSGetUncaughtExceptionHandler();
  60. NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
  61. }
  62. void InitCrashHandling()
  63. {
  64. #if ENABLE_CUSTOM_CRASH_REPORTER
  65. InitCrashReporter();
  66. #endif
  67. #if ENABLE_OBJC_UNCAUGHT_EXCEPTION_HANDLER
  68. InitObjCUEHandler();
  69. #endif
  70. }
  71. // This function will be called when AppDomain.CurrentDomain.UnhandledException event is triggered.
  72. // When running on device the app will do a hard crash and it will generate a crash log.
  73. void CrashedCheckBelowForHintsWhy()
  74. {
  75. #if ENABLE_CRASH_REPORT_SUBMISSION
  76. // Wait if app has crashed before we were able to submit an older pending crash report. This
  77. // could happen if app crashes at startup.
  78. WaitWhileCrashReportsAreSent();
  79. #endif
  80. #if ENABLE_IOS_CRASH_REPORTING || ENABLE_CUSTOM_CRASH_REPORTER
  81. // Make app crash hard here
  82. __builtin_trap();
  83. // Just in case above doesn't work
  84. abort();
  85. #endif
  86. }