From 1312772e8b19818c1add0bbf28fbeb8ba648f719 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 21 Apr 2025 01:05:24 +0200 Subject: [PATCH] Use the error dialog window, like on Windows, instead of xmessage from 1865 --- src/common/platform/posix/sdl/crashcatcher.c | 16 ++- .../platform/posix/unix/i_specialpaths.cpp | 117 ++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/src/common/platform/posix/sdl/crashcatcher.c b/src/common/platform/posix/sdl/crashcatcher.c index c88e0fe8a..35f78bce4 100644 --- a/src/common/platform/posix/sdl/crashcatcher.c +++ b/src/common/platform/posix/sdl/crashcatcher.c @@ -119,6 +119,7 @@ static void gdb_info(pid_t pid) strcpy(respfile, "gdb-respfile-XXXXXX"); if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL) { +#ifdef WHY_IS_EVERYTHING_ON_LINUX_ALWAYS_SPAMMING_THE_POOR_USER_WITH_GARBAGE fprintf(f, "attach %d\n" "shell echo \"\"\n" "shell echo \"* Loaded Libraries\"\n" @@ -137,11 +138,19 @@ static void gdb_info(pid_t pid) "thread apply all backtrace full\n" "detach\n" "quit\n", pid); +#else + fprintf(f, "attach %d\n" + "bt\n" + "detach\n" + "quit\n", pid); +#endif fclose(f); /* Run gdb and print process info. */ snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile); +#ifdef WHY_IS_EVERYTHING_ON_LINUX_ALWAYS_SPAMMING_THE_POOR_USER_WITH_GARBAGE printf("Executing: %s\n", cmd_buf); +#endif fflush(stdout); system(cmd_buf); @@ -258,9 +267,12 @@ static void crash_catcher(int signum, siginfo_t *siginfo, void *context) } } +const char *M_GetGameExe(); + static void crash_handler(const char *logfile) { const char *sigdesc = ""; + const char *dumpfile = ""; int i; if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1) @@ -367,7 +379,9 @@ static void crash_handler(const char *logfile) { char buf[512]; - if(I_FileAvailable("kdialog")) + if(I_FileAvailable(M_GetGameExe())) + snprintf(buf, sizeof(buf), "%s -showcrashreport \"%s\" \"%s\"", M_GetGameExe(), dumpfile, logfile); + else if(I_FileAvailable("kdialog")) snprintf(buf, sizeof(buf), "kdialog --title \"Very Fatal Error\" --textbox \"%s\" 800 600", logfile); else if(I_FileAvailable("gxmessage")) snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile); diff --git a/src/common/platform/posix/unix/i_specialpaths.cpp b/src/common/platform/posix/unix/i_specialpaths.cpp index 112e92ee7..036808964 100644 --- a/src/common/platform/posix/unix/i_specialpaths.cpp +++ b/src/common/platform/posix/unix/i_specialpaths.cpp @@ -238,3 +238,120 @@ FString M_GetNormalizedPath(const char* path) return fullpath; } +//=========================================================================== +// +// Crashcatcher is a C file. Thanks a lot for that! Really appreciate the +// quality work. Here's some more that fits so nicely into the codebase... +// +//=========================================================================== + +#include +#include + +#ifdef __APPLE__ +#include +#endif +#ifdef EXTERN___PROGNAME +extern const char *__progname; +#endif + +std::string exe_path() +{ + char exe_file[PATH_MAX]; +#ifdef __APPLE__ + CFBundleRef mainBundle = CFBundleGetMainBundle(); + if (mainBundle) + { + CFURLRef mainURL = CFBundleCopyBundleURL(mainBundle); + + if (mainURL) + { + int ok = CFURLGetFileSystemRepresentation ( + mainURL, (Boolean) true, (UInt8*)exe_file, PATH_MAX + ); + + if (ok) + { + return std::string(exe_file) + "/"; + } + } + } + + throw Exception("get_exe_path failed"); + +#else +#ifndef PROC_EXE_PATH +#define PROC_EXE_PATH "/proc/self/exe" +#endif + int size; + struct stat sb; + if (lstat(PROC_EXE_PATH, &sb) < 0) + { +#ifdef EXTERN___PROGNAME + char *pathenv, *name, *end; + char fname[PATH_MAX]; + char cwd[PATH_MAX]; + struct stat sba; + + exe_file[0] = '\0'; + if ((pathenv = getenv("PATH")) != nullptr) + { + for (name = pathenv; name; name = end) + { + if ((end = strchr(name, ':'))) + *end++ = '\0'; + snprintf(fname, sizeof(fname), + "%s/%s", name, (char *)__progname); + if (stat(fname, &sba) == 0) { + snprintf(exe_file, sizeof(exe_file), + "%s/", name); + break; + } + } + } + // if getenv failed or path still not found + // try current directory as last resort + if (!exe_file[0]) + { + if (getcwd(cwd, sizeof(cwd)) != nullptr) + { + snprintf(fname, sizeof(fname), + "%s/%s", cwd, (char *)__progname); + if (stat(fname, &sba) == 0) + snprintf(exe_file, sizeof(exe_file), + "%s/", cwd); + } + } + if (!exe_file[0]) + return ""; + else + return std::string(exe_file); +#else + return ""; +#endif + } + else + { + size = readlink(PROC_EXE_PATH, exe_file, PATH_MAX); + if (size < 0) + { + return strerror(errno); + } + else + { + exe_file[size] = '\0'; + return std::string(dirname(exe_file)) + "/"; + } + } +#endif + +} + +extern "C" +{ + const char *M_GetGameExe() + { + static FString s = (exe_path() + GAMENAMELOWERCASE).c_str(); + return s.GetChars(); + } +}