BsMacOSCrashHandler.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Prerequisites/BsPrerequisitesUtil.h"
  4. #include <cxxabi.h>
  5. #include <execinfo.h>
  6. #include <dlfcn.h>
  7. #include <csignal>
  8. namespace bs
  9. {
  10. CrashHandler::CrashHandler() {}
  11. CrashHandler::~CrashHandler() {}
  12. String CrashHandler::getCrashTimestamp()
  13. {
  14. std::time_t t = time(0);
  15. struct tm *now = localtime(&t);
  16. String timeStamp = "{0}{1}{2}_{3}{4}";
  17. String strYear = toString(now->tm_year, 4, '0');
  18. String strMonth = toString(now->tm_mon, 2, '0');
  19. String strDay = toString(now->tm_mday, 2, '0');
  20. String strHour = toString(now->tm_hour, 2, '0');
  21. String strMinute = toString(now->tm_min, 2, '0');
  22. return StringUtil::format(timeStamp, strYear, strMonth, strDay, strHour, strMinute);
  23. }
  24. String CrashHandler::getStackTrace()
  25. {
  26. StringStream stackTrace;
  27. void* trace[BS_MAX_STACKTRACE_DEPTH];
  28. int traceSize = backtrace(trace, BS_MAX_STACKTRACE_DEPTH);
  29. char** messages = backtrace_symbols(trace, traceSize);
  30. for (int i = 0; i < traceSize && messages != nullptr; ++i)
  31. {
  32. stackTrace << std::to_string(i) << ") " << messages[i];
  33. // Try parsing a human readable name
  34. Dl_info info;
  35. if (dladdr(trace[i], &info) && info.dli_sname)
  36. {
  37. stackTrace << ": ";
  38. if (info.dli_sname[0] == '_')
  39. {
  40. int status = -1;
  41. char* demangledName = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
  42. if(status == 0)
  43. stackTrace << demangledName;
  44. else
  45. stackTrace << info.dli_sname;
  46. free(demangledName);
  47. }
  48. else
  49. stackTrace << info.dli_sname;
  50. // Try to find the line number
  51. for (char *p = messages[i]; *p; ++p)
  52. {
  53. if (*p == '+')
  54. {
  55. stackTrace << " " << p;
  56. break;
  57. }
  58. }
  59. }
  60. if (i < traceSize - 1)
  61. stackTrace << "\n";
  62. }
  63. free(messages);
  64. return stackTrace.str();
  65. }
  66. void CrashHandler::reportCrash(const String& type,
  67. const String& description,
  68. const String& function,
  69. const String& file,
  70. UINT32 line) const
  71. {
  72. logErrorAndStackTrace(type, description, function, file, line);
  73. saveCrashLog();
  74. // Allow the debugger a chance to attach
  75. std::raise(SIGINT);
  76. }
  77. }