@@ -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; | ||||