| @@ -17,6 +17,7 @@ void createDirectory(const std::string &path); | |||||
| int getPhysicalCoreCount(); | int getPhysicalCoreCount(); | ||||
| void setThreadName(const std::string &name); | void setThreadName(const std::string &name); | ||||
| void setThreadRealTime(); | void setThreadRealTime(); | ||||
| std::string getStackTrace(); | |||||
| /** Opens a URL, also happens to work with PDFs and folders. | /** Opens a URL, also happens to work with PDFs and folders. | ||||
| Shell injection is possible, so make sure the URL is trusted or hard coded. | Shell injection is possible, so make sure the URL is trusted or hard coded. | ||||
| @@ -13,19 +13,14 @@ | |||||
| #include "app.hpp" | #include "app.hpp" | ||||
| #include "patch.hpp" | #include "patch.hpp" | ||||
| #include "ui.hpp" | #include "ui.hpp" | ||||
| #include "system.hpp" | |||||
| #include <osdialog.h> | #include <osdialog.h> | ||||
| #include <unistd.h> // for getopt | #include <unistd.h> // for getopt | ||||
| #include <signal.h> // for signal | #include <signal.h> // for signal | ||||
| #if defined ARCH_LIN | |||||
| #include <execinfo.h> // for backtrace and backtrace_symbols | |||||
| #endif | |||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| #include <Windows.h> | |||||
| #include <processthreadsapi.h> | |||||
| #include <dbghelp.h> | |||||
| #include <windows.h> // for CreateMutex | |||||
| #endif | #endif | ||||
| using namespace rack; | using namespace rack; | ||||
| @@ -38,37 +33,7 @@ static void fatalSignalHandler(int sig) { | |||||
| exit(1); | exit(1); | ||||
| caught = true; | caught = true; | ||||
| FATAL("Fatal signal %d. Backtrace:", sig); | |||||
| FATAL(""); | |||||
| int stackLen = 128; | |||||
| void *stack[stackLen]; | |||||
| #if defined ARCH_LIN | |||||
| stackLen = backtrace(stack, stackLen); | |||||
| char **strings = backtrace_symbols(stack, stackLen); | |||||
| for (int i = 0; i < stackLen; i++) { | |||||
| FATAL("%d: %s", i, strings[i]); | |||||
| } | |||||
| free(strings); | |||||
| #elif defined ARCH_MAC | |||||
| // TODO | |||||
| #elif defined ARCH_WIN | |||||
| HANDLE process = GetCurrentProcess(); | |||||
| SymInitialize(process, NULL, true); | |||||
| stackLen = CaptureStackBackTrace(0, stackLen, stack, NULL); | |||||
| SYMBOL_INFO *symbol = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256, 1); | |||||
| symbol->MaxNameLen = 255; | |||||
| symbol->SizeOfStruct = sizeof(SYMBOL_INFO); | |||||
| for (int i = 0; i < stackLen; i++) { | |||||
| SymFromAddr(process, (DWORD64) stack[i], 0, symbol); | |||||
| FATAL("%d: %s 0x%0x", i, symbol->Name, symbol->Address); | |||||
| } | |||||
| free(symbol); | |||||
| #endif | |||||
| FATAL("Fatal signal %d. Stack trace:\n%s", sig, system::getStackTrace().c_str()); | |||||
| osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Rack has crashed. See log.txt for details."); | osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Rack has crashed. See log.txt for details."); | ||||
| @@ -121,6 +86,7 @@ int main(int argc, char *argv[]) { | |||||
| signal(SIGILL, fatalSignalHandler); | signal(SIGILL, fatalSignalHandler); | ||||
| signal(SIGSEGV, fatalSignalHandler); | signal(SIGSEGV, fatalSignalHandler); | ||||
| signal(SIGTERM, fatalSignalHandler); | signal(SIGTERM, fatalSignalHandler); | ||||
| abort(); | |||||
| // Log environment | // Log environment | ||||
| INFO("%s v%s", app::APP_NAME, app::APP_VERSION); | INFO("%s v%s", app::APP_NAME, app::APP_VERSION); | ||||
| @@ -1,4 +1,5 @@ | |||||
| #include "system.hpp" | #include "system.hpp" | ||||
| #include "string.hpp" | |||||
| #include <thread> | #include <thread> | ||||
| #include <dirent.h> | #include <dirent.h> | ||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||
| @@ -6,11 +7,14 @@ | |||||
| #if defined ARCH_LIN | #if defined ARCH_LIN | ||||
| #include <pthread.h> | #include <pthread.h> | ||||
| #include <sched.h> | #include <sched.h> | ||||
| #include <execinfo.h> // for backtrace and backtrace_symbols | |||||
| #endif | #endif | ||||
| #if defined ARCH_WIN | #if defined ARCH_WIN | ||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <shellapi.h> | #include <shellapi.h> | ||||
| #include <processthreadsapi.h> | |||||
| #include <dbghelp.h> | |||||
| #endif | #endif | ||||
| @@ -110,6 +114,40 @@ void setThreadRealTime() { | |||||
| #endif | #endif | ||||
| } | } | ||||
| std::string getStackTrace() { | |||||
| int stackLen = 128; | |||||
| void *stack[stackLen]; | |||||
| std::string s; | |||||
| #if defined ARCH_LIN | |||||
| stackLen = backtrace(stack, stackLen); | |||||
| char **strings = backtrace_symbols(stack, stackLen); | |||||
| for (int i = 0; i < stackLen; i++) { | |||||
| s += string::f("%d: %s\n", stackLen - i - 1, strings[i]); | |||||
| } | |||||
| free(strings); | |||||
| #elif defined ARCH_MAC | |||||
| // TODO | |||||
| #elif defined ARCH_WIN | |||||
| HANDLE process = GetCurrentProcess(); | |||||
| SymInitialize(process, NULL, true); | |||||
| stackLen = CaptureStackBackTrace(0, stackLen, stack, NULL); | |||||
| SYMBOL_INFO *symbol = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256, 1); | |||||
| symbol->MaxNameLen = 255; | |||||
| symbol->SizeOfStruct = sizeof(SYMBOL_INFO); | |||||
| for (int i = 0; i < stackLen; i++) { | |||||
| SymFromAddr(process, (DWORD64) stack[i], 0, symbol); | |||||
| s += string::f("%d: %s 0x%0x", stackLen - i - 1, symbol->Name, symbol->Address); | |||||
| } | |||||
| free(symbol); | |||||
| #endif | |||||
| return s; | |||||
| } | |||||
| void openBrowser(const std::string &url) { | void openBrowser(const std::string &url) { | ||||
| #if defined ARCH_LIN | #if defined ARCH_LIN | ||||
| std::string command = "xdg-open " + url; | std::string command = "xdg-open " + url; | ||||