diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 7062ca2c7..99503f29c 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -26,6 +26,12 @@ else () ) set(LIB_DXCOMPILER "libdxcompiler.so") + # needed for proper names in crash stacktrace + set_target_properties(WickedEngineEditor + PROPERTIES + ENABLE_EXPORTS ON + ) + endif () # Copy content to build folder: diff --git a/Editor/main_SDL2.cpp b/Editor/main_SDL2.cpp index aaaffa481..38491a855 100644 --- a/Editor/main_SDL2.cpp +++ b/Editor/main_SDL2.cpp @@ -6,6 +6,13 @@ #include "icon.c" +#ifdef __linux__ +# include +# include +# include +# include +#endif + using namespace std; Editor editor; @@ -92,8 +99,71 @@ void set_window_icon(SDL_Window *window) { SDL_FreeSurface(icon); } +#ifdef __linux__ + +void crash_handler(int sig) +{ + void* btbuf[100]; + + char outbuf[256]; + + size_t size = backtrace(btbuf, 100); + snprintf( + outbuf, sizeof(outbuf), + "Signal: %i (%s)\n" + "Version: %s\nStacktrace:\n", + sig, + sigdescr_np(sig), + wi::version::GetVersionString() + ); + + fprintf( + stderr, + "\e[31m" // red + "The editor just crashed, sorry about that! If you make a bug report, please include the following information:\n\n%s", + outbuf + ); + backtrace_symbols_fd(btbuf, size, STDERR_FILENO); // backtrace_symbols does a malloc which could crash, backtrace_symbols_fd does not. + fprintf(stderr, "\e[m"); // back to normal + + // finally, we also try to write the crash data to a file + // this might fail because we're in a weird state right now, but there's no harm done if it doesn't work + + // Use C interface because some stuff in the c++ stdlib could be calling malloc + + const char* filename = "wicked-editor-crash-log.txt"; + + FILE* logfile = fopen(filename, "w"); + + if (logfile != nullptr) + { + fputs(outbuf, logfile); + fflush(logfile); + backtrace_symbols_fd(btbuf, size, fileno(logfile)); + fclose(logfile); + char cwdbuf[200]; + fprintf(stderr, "\e[1mcrash log written to %s/%s\e[m\n", getcwd(cwdbuf, sizeof(cwdbuf)), filename); + } + exit(1); +} + +#endif + int main(int argc, char *argv[]) { + +#ifdef __linux__ + // dummy backtrace() call to force libgcc to be loaded ahead of time. + // Otherwise it might lead to malloc calls in the crash_handler, which we want to avoid + void* dummy[1]; + backtrace(dummy, 1); + + for (int sig : std::array{SIGABRT, SIGBUS, SIGILL, SIGFPE, SIGSEGV}) + { + signal(sig, crash_handler); + } +#endif + wi::arguments::Parse(argc, argv); sdl2::sdlsystem_ptr_t system = sdl2::make_sdlsystem(SDL_INIT_EVERYTHING | SDL_INIT_EVENTS); diff --git a/WickedEngine/wiBacklog.h b/WickedEngine/wiBacklog.h index c5ce5501a..897561d64 100644 --- a/WickedEngine/wiBacklog.h +++ b/WickedEngine/wiBacklog.h @@ -8,8 +8,8 @@ #include #include -#define wilog_level(str,level,...) {char text[1024] = {}; snprintf(text, sizeof(text), str, ## __VA_ARGS__); wi::backlog::post(text, level);} -#define wilog_messagebox(str,...) {char text[1024] = {}; snprintf(text, sizeof(text), str, ## __VA_ARGS__); wi::backlog::post(text, wi::backlog::LogLevel::Error); wi::helper::messageBox(text, "Error!");} +#define wilog_level(str,level,...) {char text[1024]; snprintf(text, sizeof(text), str, ## __VA_ARGS__); wi::backlog::post(text, level);} +#define wilog_messagebox(str,...) {char text[1024]; snprintf(text, sizeof(text), str, ## __VA_ARGS__); wi::backlog::post(text, wi::backlog::LogLevel::Error); wi::helper::messageBox(text, "Error!");} #define wilog_warning(str,...) {wilog_level(str, wi::backlog::LogLevel::Warning, ## __VA_ARGS__);} #define wilog_error(str,...) {wilog_level(str, wi::backlog::LogLevel::Error, ## __VA_ARGS__);} #define wilog(str,...) {wilog_level(str, wi::backlog::LogLevel::Default, ## __VA_ARGS__);}