diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 5d0b3f6067..32e0f21517 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -78,6 +78,7 @@ /* static */ const char *CrashLog::message = NULL; /* static */ char *CrashLog::gamelog_buffer = NULL; /* static */ const char *CrashLog::gamelog_last = NULL; +/* static */ const CrashLog *CrashLog::main_thread_pending_crashlog = NULL; char *CrashLog::LogCompiler(char *buffer, const char *last) const { @@ -534,8 +535,33 @@ bool CrashLog::MakeCrashLog() const printf("Crash dump written to %s. Please add this file to any bug reports.\n\n", filename); } + if (IsNonMainThread()) { + printf("Asking main thread to write crash savegame and screenshot...\n\n"); + CrashLog::main_thread_pending_crashlog = this; + _exit_game = true; + CSleep(60000); + if (!CrashLog::main_thread_pending_crashlog) return ret; + printf("Main thread did not write crash savegame and screenshot within 60s, trying it from this thread...\n\n"); + } + CrashLog::main_thread_pending_crashlog = nullptr; + bret = CrashLog::MakeCrashSavegameAndScreenshot(); + if (!bret) ret = false; + + return ret; +} + +/** + * Makes a crash dump and crash savegame. It uses DEBUG to write + * information like paths to the console. + * @return true when everything is made successfully. + */ +bool CrashLog::MakeCrashSavegameAndScreenshot() const +{ + char filename[MAX_PATH]; + bool ret = true; + printf("Writing crash savegame...\n"); - bret = this->WriteSavegame(filename, lastof(filename)); + bool bret = this->WriteSavegame(filename, lastof(filename)); if (bret) { printf("Crash savegame written to %s. Please add this file and the last (auto)save to any bug reports.\n\n", filename); } else { @@ -555,6 +581,18 @@ bool CrashLog::MakeCrashLog() const return ret; } +/* static */ void CrashLog::MainThreadExitCheckPendingCrashlog() +{ + const CrashLog *cl = CrashLog::main_thread_pending_crashlog; + if (cl) { + CrashLog::main_thread_pending_crashlog = nullptr; + cl->MakeCrashSavegameAndScreenshot(); + + CrashLog::AfterCrashLogCleanup(); + abort(); + } +} + /** * Sets a message for the error message handler. * @param message The error message of the error. diff --git a/src/crashlog.h b/src/crashlog.h index 8948a8acb4..72077d2bbf 100644 --- a/src/crashlog.h +++ b/src/crashlog.h @@ -127,6 +127,7 @@ public: bool WriteScreenshot(char *filename, const char *filename_last) const; bool MakeCrashLog() const; + bool MakeCrashSavegameAndScreenshot() const; /** * Initialiser for crash logs; do the appropriate things so crashes are @@ -141,6 +142,10 @@ public: inline const char *GetMessage() const { return this->message; } static const char *GetAbortCrashlogReason(); + + static const CrashLog *main_thread_pending_crashlog; + + static void MainThreadExitCheckPendingCrashlog(); }; #endif /* CRASHLOG_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 43c22fdffa..a9b9f5fbe1 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -890,6 +890,8 @@ int openttd_main(int argc, char *argv[]) VideoDriver::GetInstance()->MainLoop(); + CrashLog::MainThreadExitCheckPendingCrashlog(); + WaitTillSaved(); /* only save config if we have to */