From ee555c92d86efd738e3b06dbc67e273e7e76ac30 Mon Sep 17 00:00:00 2001 From: DepressedTWM Date: Fri, 14 Aug 2026 12:30:10 +0400 Subject: [PATCH] Engine SEGFAULT on crash() when ruby is not initialized fixed --- binding-mri/binding-mri.cpp | 2 + src/bitmap.cpp | 6 +- src/disposable.h | 2 +- src/gl-fun.cpp | 11 +++- src/main.cpp | 2 +- src/meow.cpp | 113 ++++++++++++++++++++++++------------ src/meow.h | 6 +- 7 files changed, 95 insertions(+), 47 deletions(-) diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index a8a9cdc..e22860c 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -534,6 +534,7 @@ static void mriBindingExecute(){ RUBY_INIT_STACK; ruby_init(); ruby_init_loadpath(); + is_ruby_initialized = true; rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding())); Config &conf = shState->rtData().config; if (!conf.rubyLoadpaths.empty()){ @@ -558,6 +559,7 @@ static void mriBindingExecute(){ showExc(exc, btData); shState->rtData().rqTermAck.set(); + is_ruby_initialized = false; } static void mriBindingTerminate(){ diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 8539a6e..4d279bc 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -48,7 +48,7 @@ #define GUARD_MEGA \ { \ if (p->megaSurface) \ - crash(Exception::MKXPError, "Operation not supported for mega surfaces"); \ + ErrorMsg(Exception::MKXPError, "Operation not supported for mega surfaces"); \ } #define OUTLINE_SIZE 1 @@ -225,7 +225,7 @@ Bitmap::Bitmap(const char *filename){ SDL_Surface *imgSurf = handler.surf; if (!imgSurf) - crash(Exception::SDLError, "Error loading image '%s': %s", filename, SDL_GetError()); + ErrorMsg(Exception::SDLError, "Error loading image '%s': %s", filename, SDL_GetError()); p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888); @@ -261,7 +261,7 @@ Bitmap::Bitmap(const char *filename){ Bitmap::Bitmap(int width, int height){ if (width <= 0 || height <= 0) - crash(Exception::RGSSError, "failed to create bitmap"); + ErrorMsg(Exception::RGSSError, "failed to create bitmap"); TEXFBO tex = shState->texPool().request(width, height); diff --git a/src/disposable.h b/src/disposable.h index 3874095..f05bc05 100644 --- a/src/disposable.h +++ b/src/disposable.h @@ -62,7 +62,7 @@ public: protected: void guardDisposed() const{ if (isDisposed()) - crash(Exception::RGSSError, "disposed %s", klassName()); + ErrorMsg(Exception::RGSSError, "disposed %s", klassName()); } private: diff --git a/src/gl-fun.cpp b/src/gl-fun.cpp index 20b5835..6fc2fec 100644 --- a/src/gl-fun.cpp +++ b/src/gl-fun.cpp @@ -90,8 +90,13 @@ void initGLFunctions(){ /* Assume single digit */ int glMajor = *ver - '0'; - if (glMajor < 2) - crash(Exception::MKXPError, "At least OpenGL (ES) 2.0 is required"); + if (glMajor < 2){ + #ifdef GLES2_HEADER + ErrorMsg("At least OpenGL ES 2.0 is required"); + #else + ErrorMsg("At least OpenGL 2.0 is required"); + #endif + } if (gles){ GL_ES_FUN; @@ -126,7 +131,7 @@ void initGLFunctions(){ } } else{ - crash(Exception::MKXPError, "No FBO support available"); + ErrorMsg("No FBO support available"); } /* VAO entrypoints */ diff --git a/src/main.cpp b/src/main.cpp index da46347..3785331 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -202,7 +202,7 @@ static void setGamePathInRegistry() { //TODO handle this for Linux/Mac } int main(int argc, char *argv[]){ - Debug() << VERSION_STRING; + crash(Exception::SDLError, "DEBUGTEST"); startTime = boost::chrono::high_resolution_clock::now(); loadLanguageMetadata(); //there will be a segfault on fclose if I don't move it here SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); diff --git a/src/meow.cpp b/src/meow.cpp index e6c3264..54a263f 100644 --- a/src/meow.cpp +++ b/src/meow.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #undef vsnprintf #undef snprintf #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) @@ -53,6 +54,57 @@ static inline const char* glGetStringInt(GLenum name){ return (const char*) gl.GetString(name); } +static void get_reason_and_solution(Exception::Type t) { + switch (t) { + case Exception::ModLoaderError: + crash_reason = "Broken mod"; + crash_possible_solution = "Fix mode manualy or ask developer to fix it or delete mod"; + break; + case Exception::NoFileError: + crash_reason = "Broken installation"; + crash_possible_solution = "Try reinstall game"; + break; + case Exception::ShaderError: + crash_reason = "Broken Shader"; + crash_possible_solution = "Try reinstall game"; + break; + case Exception::RGSSError: + crash_reason = "Internal Error"; + crash_possible_solution = "Try reinstall game or disable some mods"; + break; + case Exception::RUBYError: + crash_reason = "Internal Error"; + crash_possible_solution = "Try reinstall game or disable some mods"; + break; + case Exception::IOError: + crash_reason = "Broken installation"; + crash_possible_solution = "Try reinstall game"; + break; + case Exception::TypeError: + crash_reason = "Internal Error"; + crash_possible_solution = "Try reinstall game or disable some mods"; + break; + case Exception::ArgumentError: + crash_reason = "Internal error"; + crash_possible_solution = "Try reinstall game or disable some mods"; + break; + case Exception::PHYSFSError: + crash_reason = "Internal error"; + crash_possible_solution = "Maybe you tryed load corrupted mod via modloader, try delete it"; + break; + case Exception::SDLError: + crash_reason = "Internal error"; + crash_possible_solution = "Internal Engine Error, maybe something wrong with your device or operating system"; + break; + case Exception::MKXPError: + crash_reason = "Internal error"; + crash_possible_solution = "Try reinstall game or disable some mods"; + break; + default: + break; + } +} + void crash(Exception::Type t, const char *fmt, ...) { static char crash_message[1024]; static const char* crash_reason = nullptr; @@ -70,44 +122,11 @@ void crash(Exception::Type t, const char *fmt, ...) { SDL_vsnprintf(crash_message, sizeof(crash_message), fmt, args); va_end(args); - - //TODO: rewrite to use switch :3 - if (t == Exception::ModLoaderError) { - crash_reason = "Broken mod"; - crash_possible_solution = "Fix mode manualy or ask developer to fix it or delete mod"; - } else if (t == Exception::NoFileError) { - crash_reason = "Broken installation"; - crash_possible_solution = "Try reinstall game"; - } else if (t == Exception::ShaderError) { - crash_reason = "Broken Shader"; - crash_possible_solution = "Try reinstall game"; - } else if (t == Exception::RGSSError) { - crash_reason = "Internal Error"; - crash_possible_solution = "Try reinstall game or disable some mods"; - } else if (t == Exception::RUBYError) { - crash_reason = "Internal Error"; - crash_possible_solution = "Try reinstall game or disable some mods"; - } else if (t == Exception::IOError) { - crash_reason = "Broken installation"; - crash_possible_solution = "Try reinstall game"; - } else if (t == Exception::TypeError) { - crash_reason = "Internal Error"; - crash_possible_solution = "Try reinstall game or disable some mods"; - } else if (t == Exception::ArgumentError) { - crash_reason = "Internal error"; - crash_possible_solution = "Try reinstall game or disable some mods"; - } else if (t == Exception::PHYSFSError) { - crash_reason = "Internal error"; - crash_possible_solution = "Maybe you tryed load corrupted mod via modloader, try delete it"; - } else if (t == Exception::SDLError) { - crash_reason = "Internal error"; - crash_possible_solution = "Internal Engine Error, maybe something wrong with your device or operating system"; - } else if (t == Exception::MKXPError) { - crash_reason = "Internal error"; - crash_possible_solution = "Try reinstall game or disable some mods"; - } + get_reason_and_solution(t); show_crash_sceen = true; - rb_exit(-1); + //Protect against segfaults + if(is_ruby_initialized) + ruby_stop(-1); } void crash_screen(SDL_Window* win){ @@ -293,6 +312,26 @@ void ErrorMsg(const char *fmt, ...) { show_crash_sceen = true; } +void ErrorMsg(Exception::Type t, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + + va_list args_copy; + va_copy(args_copy, args); + unsigned int len = (unsigned int)SDL_vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + char *buf = (char*)SDL_malloc((size_t)len + 1); + if (!buf) { va_end(args); return; } + + SDL_vsnprintf(buf, (size_t)len + 1, fmt, args); + va_end(args); + + SDL_snprintf(crash_message, sizeof(crash_message), "%s", buf); + get_reason_and_solution(t); + show_crash_sceen = true; +} + void WarnMsg(const char *fmt, ...) { va_list args; va_start(args, fmt); diff --git a/src/meow.h b/src/meow.h index 7853052..504869a 100644 --- a/src/meow.h +++ b/src/meow.h @@ -7,10 +7,12 @@ inline std::vector logs = {}; inline bool show_crash_sceen = false; -inline char crash_reason[1024] = "Unknown"; +inline bool is_ruby_initialized = false; inline char crash_message[1024] = ""; -inline char crash_possible_solution[1024] = "Unknown"; +inline const char* crash_reason = "Unknown"; +inline const char* crash_possible_solution = "Unknown"; void crash(Exception::Type t, const char *fmt, ...); void ErrorMsg(const char *fmt, ...); +void ErrorMsg(Exception::Type t, const char *fmt, ...); void WarnMsg(const char *fmt, ...); void crash_screen(SDL_Window* win);