Skip to content

Commit

Permalink
linux: add simple crash handler that dumps stacktrace (#1020)
Browse files Browse the repository at this point in the history
Since the Linux version seems much more unstable than the Windows one,
having more information where the crash occured will help with figuring
out where the problems are.

This commit adds a simple crash handler that dumps out the stacktrace,
it's only supported on Linux.
  • Loading branch information
brakhane authored Jan 16, 2025
1 parent 73d7a0d commit 17bf75f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Editor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
70 changes: 70 additions & 0 deletions Editor/main_SDL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

#include "icon.c"

#ifdef __linux__
# include <execinfo.h>
# include <csignal>
# include <cstdio>
# include <unistd.h>
#endif

using namespace std;

Editor editor;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions WickedEngine/wiBacklog.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#include <string>
#include <cassert>

#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__);}
Expand Down

0 comments on commit 17bf75f

Please sign in to comment.