10 #include "../../stdafx.h"
11 #include "../../crashlog.h"
12 #include "../../fileio_func.h"
13 #include "../../string_func.h"
14 #include "../../gamelog.h"
15 #include "../../saveload/saveload.h"
19 #include <sys/utsname.h>
21 #if defined(__GLIBC__)
23 # include <execinfo.h>
26 #ifdef WITH_UNOFFICIAL_BREAKPAD
27 # include <client/linux/handler/exception_handler.h>
30 #if defined(__EMSCRIPTEN__)
31 # include <emscripten.h>
33 # define _exit emscripten_force_exit
38 #include "../../safeguards.h"
41 static constexpr
int _signals_to_handle[] = { SIGSEGV, SIGABRT, SIGFPE, SIGBUS, SIGILL, SIGQUIT };
53 survey[
"reason"] = strsignal(
signum);
56 void SurveyStacktrace([[maybe_unused]] nlohmann::json &survey)
const override
58 #if defined(__GLIBC__)
60 int trace_size = backtrace(trace,
lengthof(trace));
62 survey = nlohmann::json::array();
64 char **messages = backtrace_symbols(trace, trace_size);
65 for (
int i = 0; i < trace_size; i++) {
66 survey.push_back(messages[i]);
72 #ifdef WITH_UNOFFICIAL_BREAKPAD
73 static bool MinidumpCallback(
const google_breakpad::MinidumpDescriptor &descriptor,
void *context,
bool succeeded)
78 std::rename(descriptor.path(), crashlog->crashdump_filename.c_str());
84 return google_breakpad::ExceptionHandler::WriteMinidump(
_personal_dir, MinidumpCallback,
this);
88 bool TryExecute(std::string_view section_name, std::function<
bool()> &&func)
override
94 fmt::print(
"Something went wrong when attempting to fill {} section of the crash log.\n", section_name);
102 sigprocmask(SIG_UNBLOCK, &sigs,
nullptr);
146 sigaddset(&sigs, signum);
150 memset(&sa, 0,
sizeof(sa));
151 sa.sa_flags = SA_RESTART;
153 sigemptyset(&sa.sa_mask);
154 sa.sa_handler = handler;
158 sigaction(signum, &sa,
nullptr);
172 fmt::print(
"Something went seriously wrong when creating the crash log. Aborting.\n");
194 sigprocmask(SIG_UNBLOCK, &sigs, &old_sigset);
197 fmt::print(
"A serious fault condition occurred in the game. The game will shut down.\n");
198 fmt::print(
"As you loaded an emergency savegame no crash information will be generated.\n");
203 fmt::print(
"A serious fault condition occurred in the game. The game will shut down.\n");
204 fmt::print(
"As you loaded an savegame for which you do not have the required NewGRFs\n");
205 fmt::print(
"no crash information will be generated.\n");
bool SaveloadCrashWithMissingNewGRFs()
Did loading the savegame cause a crash? If so, were NewGRFs missing?
Unix implementation for the crash logger.
CrashLogUnix(int signum)
A crash log is always generated by signal.
void SurveyCrash(nlohmann::json &survey) const override
Convert system crash reason to JSON.
bool try_execute_active
Whether we are in a TryExecute block.
jmp_buf internal_fault_jmp_buf
Buffer to track the long jump set setup.
static CrashLogUnix * current
Points to the current crash log.
bool TryExecute(std::string_view section_name, std::function< bool()> &&func) override
Execute the func() and return its value.
int signum
Signal that has been thrown.
Helper class for creating crash logs.
void MakeCrashLog()
Makes the crash log, writes it to a file and then subsequently tries to make a crash dump and crash s...
std::string CreateFileName(const char *ext, bool with_dir=true) const
Create a timestamped filename.
virtual bool WriteCrashDump()
Write the (crash) dump to a file.
static void InitThread()
Prepare crash log handler for a newly started thread.
static void AfterCrashLogCleanup()
Try to close the sound/video stuff so it doesn't keep lingering around incorrect video states or so,...
static void InitialiseCrashLog()
Initialiser for crash logs; do the appropriate things so crashes are handled by our crash handler ins...
bool TestEmergency()
Finds out if current game is a loaded emergency savegame.
static void CDECL HandleInternalCrash([[maybe_unused]] int signum)
Entry point for a crash that happened during the handling of a crash.
static constexpr int _signals_to_handle[]
The signals we want our crash handler to handle.
static void CDECL HandleCrash(int signum)
Entry point for the crash handler.
static sigset_t SetSignals(void(*handler)(int))
Set a signal handler for all signals we want to capture.
std::string _personal_dir
custom directory for personal settings, saves, newgrf, etc.
Gamelog _gamelog
Gamelog instance.
void free(const void *ptr)
Version of the standard free that accepts const pointers.
#define lengthof(array)
Return the length of an fixed size array.