Files
WickedEngine/Editor/main_SDL2.cpp
T
Dennis Brakhane 17bf75fd35 linux: add simple crash handler that dumps stacktrace (#1020)
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.
2025-01-16 08:42:40 +01:00

219 lines
6.2 KiB
C++

#include "stdafx.h"
#include "Editor.h"
#include "sdl2.h"
#include <fstream>
#include "icon.c"
#ifdef __linux__
# include <execinfo.h>
# include <csignal>
# include <cstdio>
# include <unistd.h>
#endif
using namespace std;
Editor editor;
int sdl_loop()
{
bool quit = false;
while (!quit)
{
editor.Run();
SDL_Event event;
while(SDL_PollEvent(&event)){
bool textinput_action_delete = false;
switch(event.type){
case SDL_QUIT:
quit = true;
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_CLOSE: // exit editor
quit = true;
break;
case SDL_WINDOWEVENT_RESIZED:
// Tells the engine to reload window configuration (size and dpi)
editor.SetWindow(editor.window);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
editor.is_window_active = false;
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
editor.is_window_active = true;
editor.HotReload();
break;
default:
break;
}
case SDL_KEYDOWN:
if(event.key.keysym.scancode == SDL_SCANCODE_BACKSPACE
|| event.key.keysym.scancode == SDL_SCANCODE_DELETE
|| event.key.keysym.scancode == SDL_SCANCODE_KP_BACKSPACE){
wi::gui::TextInputField::DeleteFromInput();
textinput_action_delete = true;
}
break;
case SDL_TEXTINPUT:
if(!textinput_action_delete){
if(event.text.text[0] >= 21){
wi::gui::TextInputField::AddInput(event.text.text[0]);
}
}
break;
default:
break;
}
wi::input::sdlinput::ProcessEvent(event);
}
}
return 0;
}
void set_window_icon(SDL_Window *window) {
// these masks are needed to tell SDL_CreateRGBSurface(From)
// to assume the data it gets is byte-wise RGB(A) data
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int shift = (gimp_image.bytes_per_pixel == 3) ? 8 : 0;
rmask = 0xff000000 >> shift;
gmask = 0x00ff0000 >> shift;
bmask = 0x0000ff00 >> shift;
amask = 0x000000ff >> shift;
#else // little endian, like x86
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = (gimp_image.bytes_per_pixel == 3) ? 0 : 0xff000000;
#endif
SDL_Surface* icon = SDL_CreateRGBSurfaceFrom((void*)gimp_image.pixel_data, gimp_image.width,
gimp_image.height, gimp_image.bytes_per_pixel*8, gimp_image.bytes_per_pixel*gimp_image.width,
rmask, gmask, bmask, amask);
SDL_SetWindowIcon(window, icon);
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);
if (*system) {
throw sdl2::SDLError("Error creating SDL2 system");
}
int width = 1920;
int height = 1080;
bool fullscreen = false;
wi::Timer timer;
if (editor.config.Open("config.ini"))
{
if (editor.config.Has("width"))
{
width = editor.config.GetInt("width");
height = editor.config.GetInt("height");
}
fullscreen = editor.config.GetBool("fullscreen");
editor.allow_hdr = editor.config.GetBool("allow_hdr");
wi::backlog::post("config.ini loaded in " + std::to_string(timer.elapsed_milliseconds()) + " milliseconds\n");
}
width = std::max(100, width);
height = std::max(100, height);
sdl2::window_ptr_t window = sdl2::make_window(
"Wicked Editor",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
if (!window) {
throw sdl2::SDLError("Error creating window");
}
set_window_icon(window.get());
if (fullscreen)
{
//SDL_SetWindowFullscreen(window.get(), SDL_TRUE);
//SDL_SetWindowFullscreen(window.get(), SDL_WINDOW_FULLSCREEN);
SDL_SetWindowFullscreen(window.get(), SDL_WINDOW_FULLSCREEN_DESKTOP);
}
editor.SetWindow(window.get());
int ret = sdl_loop();
return ret;
}