Engine SEGFAULT on crash() when ruby is not initialized fixed

This commit is contained in:
DepressedTWM 2026-08-14 12:30:10 +04:00
parent 59e271639f
commit ee555c92d8
7 changed files with 95 additions and 47 deletions

View file

@ -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(){

View file

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

View file

@ -62,7 +62,7 @@ public:
protected:
void guardDisposed() const{
if (isDisposed())
crash(Exception::RGSSError, "disposed %s", klassName());
ErrorMsg(Exception::RGSSError, "disposed %s", klassName());
}
private:

View file

@ -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 */

View file

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

View file

@ -22,6 +22,7 @@
#include <string>
#include <vector>
#include <ruby/version.h>
#include <ruby/internal/interpreter.h>
#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);

View file

@ -7,10 +7,12 @@
inline std::vector<std::string> 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);