mirror of https://github.com/OpenRCT2/OpenRCT2.git
clean up and refactor the crash handler
This commit is contained in:
parent
9bb9e1af82
commit
51a7e3f278
|
@ -33,13 +33,13 @@
|
|||
#include "network/http.h"
|
||||
#include "network/network.h"
|
||||
#include "openrct2.h"
|
||||
#include "platform/crash.h"
|
||||
#include "platform/platform.h"
|
||||
#include "ride/ride.h"
|
||||
#include "title.h"
|
||||
#include "util/sawyercoding.h"
|
||||
#include "util/util.h"
|
||||
#include "world/mapgen.h"
|
||||
#include "platform/crash.h"
|
||||
|
||||
#if defined(__unix__)
|
||||
#include <sys/mman.h>
|
||||
|
@ -185,11 +185,7 @@ bool openrct2_initialise()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Exception handling - breakpad
|
||||
// Uses user data directory for storing dumps
|
||||
CExceptionHandler eh;
|
||||
// never free
|
||||
eh = newCExceptionHandlerSimple();
|
||||
crash_init();
|
||||
|
||||
if (!openrct2_setup_rct2_segment()) {
|
||||
log_fatal("Unable to load RCT2 data sector");
|
||||
|
|
|
@ -1,105 +1,135 @@
|
|||
#include "crash.h"
|
||||
#include <SDL_platform.h>
|
||||
#include "crash.h"
|
||||
|
||||
#ifdef USE_BREAKPAD
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <breakpad/client/windows/handler/exception_handler.h>
|
||||
#include <string>
|
||||
#include <ShlObj.h>
|
||||
#define BREAKPAD_PATH "."
|
||||
#if defined(__WINDOWS__)
|
||||
#include <breakpad/client/windows/handler/exception_handler.h>
|
||||
#include <string>
|
||||
#include <ShlObj.h>
|
||||
#elif defined(__LINUX__)
|
||||
#include <breakpad/client/linux/handler/exception_handler.h>
|
||||
#define BREAKPAD_PATH "/tmp"
|
||||
#else
|
||||
#error Breakpad support not implemented yet for this platform
|
||||
#endif __WINDOWS__
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <breakpad/client/linux/handler/exception_handler.h>
|
||||
#define BREAKPAD_PATH "/tmp"
|
||||
#endif __LINUX__
|
||||
#error Breakpad support not implemented yet for this platform
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "platform.h"
|
||||
#include "../localisation/language.h"
|
||||
#include "../scenario.h"
|
||||
#include "../localisation/language.h"
|
||||
#include "../scenario.h"
|
||||
#include "platform.h"
|
||||
}
|
||||
|
||||
#include "../core/Console.hpp"
|
||||
|
||||
static bool dumpCallback(const wchar_t *dump_path, const wchar_t *minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool succeeded) {
|
||||
if (!succeeded) {
|
||||
const char *msg = "Failed to create the dump. Nothing left to do. Please file an issue with OpenRCT2 on Github and provide latest save.";
|
||||
log_fatal(msg);
|
||||
MessageBoxA(NULL, msg, "OpenRCT2", MB_OK);
|
||||
return succeeded;
|
||||
}
|
||||
char *buffer_path = widechar_to_utf8(dump_path);
|
||||
char *buffer_minidump = widechar_to_utf8(minidump_id);
|
||||
char dump_file_path[MAX_PATH];
|
||||
char save_file_path[MAX_PATH];
|
||||
sprintf(dump_file_path, "%s%s.dmp", buffer_path, buffer_minidump);
|
||||
sprintf(save_file_path, "%s%s.sv6", buffer_path, buffer_minidump);
|
||||
log_fatal("Dump path: %s", buffer_path);
|
||||
log_fatal("minidump id: %s", buffer_minidump);
|
||||
log_fatal("Version: %s", OPENRCT2_VERSION);
|
||||
log_fatal("Commit: %s", OPENRCT2_COMMIT_SHA1_SHORT);
|
||||
SDL_RWops* rw = SDL_RWFromFile(save_file_path, "wb+");
|
||||
bool saved = false;
|
||||
if (rw != NULL) {
|
||||
scenario_save(rw, 0x80000000);
|
||||
saved = true;
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
char message[MAX_PATH * 2];
|
||||
sprintf(message, "A crash has occurred and dump was created at %s. Please create an issue with OpenRCT2 on Github and provide the dump and %s. Version: %s, Commit: %s",
|
||||
dump_file_path, saved ? save_file_path : "latest save", OPENRCT2_VERSION, OPENRCT2_COMMIT_SHA1_SHORT);
|
||||
// Cannot use platform_show_messagebox here, it tries to set parent window already dead.
|
||||
MessageBoxA(NULL, message, "OpenRCT2", MB_OK);
|
||||
HRESULT coinit_result = CoInitialize(NULL);
|
||||
if (coinit_result == S_OK) {
|
||||
//ShellExecute(NULL, "explore", message, NULL, NULL, 5);
|
||||
ITEMIDLIST *pidl = ILCreateFromPath(buffer_path);
|
||||
ITEMIDLIST *files[2];
|
||||
files[0] = ILCreateFromPath(dump_file_path);
|
||||
int files_count = 1;
|
||||
if (saved) {
|
||||
files[1] = ILCreateFromPath(save_file_path);
|
||||
files_count = 2;
|
||||
}
|
||||
if (pidl) {
|
||||
HRESULT res = SHOpenFolderAndSelectItems(pidl, files_count, (LPCITEMIDLIST *)files, 0);
|
||||
ILFree(pidl);
|
||||
ILFree(files[0]);
|
||||
if (saved) {
|
||||
ILFree(files[1]);
|
||||
}
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
free(buffer_path);
|
||||
free(buffer_minidump);
|
||||
return succeeded;
|
||||
#define WSZ(x) L"" x
|
||||
|
||||
static bool OnCrash(const wchar_t * dumpPath,
|
||||
const wchar_t * miniDumpId,
|
||||
void * context,
|
||||
EXCEPTION_POINTERS * exinfo,
|
||||
MDRawAssertionInfo * assertion,
|
||||
bool succeeded)
|
||||
{
|
||||
if (!succeeded)
|
||||
{
|
||||
constexpr char * DumpFailedMessage = "Failed to create the dump. Nothing left to do. Please file an issue with OpenRCT2 on Github and provide latest save.";
|
||||
printf("%s\n", DumpFailedMessage);
|
||||
MessageBoxA(NULL, DumpFailedMessage, OPENRCT2_NAME, MB_OK | MB_ICONERROR);
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
wchar_t dumpFilePath[MAX_PATH];
|
||||
wchar_t saveFilePath[MAX_PATH];
|
||||
wsprintfW(dumpFilePath, L"%s%s.dmp", dumpPath, miniDumpId);
|
||||
wsprintfW(saveFilePath, L"%s%s.sv6", dumpPath, miniDumpId);
|
||||
|
||||
wprintf(L"Dump Path: %s\n", dumpFilePath);
|
||||
wprintf(L"Dump Id: %s\n", miniDumpId);
|
||||
wprintf(L"Version: %s\n", WSZ(OPENRCT2_VERSION));
|
||||
wprintf(L"Commit: %s\n", WSZ(OPENRCT2_COMMIT_SHA1_SHORT));
|
||||
|
||||
utf8 * saveFilePathUTF8 = widechar_to_utf8(saveFilePath);
|
||||
SDL_RWops * rw = SDL_RWFromFile(saveFilePathUTF8, "wb+");
|
||||
free(saveFilePathUTF8);
|
||||
|
||||
bool savedGameDumped = false;
|
||||
if (rw != NULL) {
|
||||
scenario_save(rw, 0x80000000);
|
||||
savedGameDumped = true;
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
|
||||
constexpr wchar_t * MessageFormat = L"A crash has occurred and dump was created at\n%s.\n\nPlease create an issue with OpenRCT2 on Github and provide the dump and save.\n\nVersion: %s\nCommit: %s";
|
||||
wchar_t message[MAX_PATH * 2];
|
||||
swprintf_s(message,
|
||||
MessageFormat,
|
||||
dumpFilePath,
|
||||
WSZ(OPENRCT2_VERSION),
|
||||
WSZ(OPENRCT2_COMMIT_SHA1_SHORT));
|
||||
|
||||
// Cannot use platform_show_messagebox here, it tries to set parent window already dead.
|
||||
MessageBoxW(NULL, message, WSZ(OPENRCT2_NAME), MB_OK | MB_ICONERROR);
|
||||
HRESULT coInitializeResult = CoInitialize(NULL);
|
||||
if (SUCCEEDED(coInitializeResult))
|
||||
{
|
||||
ITEMIDLIST * pidl = ILCreateFromPathW(dumpPath);
|
||||
ITEMIDLIST * files[2];
|
||||
uint32 numFiles = 0;
|
||||
|
||||
files[numFiles++] = ILCreateFromPathW(dumpFilePath);
|
||||
if (savedGameDumped)
|
||||
{
|
||||
files[numFiles++] = ILCreateFromPathW(saveFilePath);
|
||||
}
|
||||
if (pidl != nullptr) {
|
||||
HRESULT result = SHOpenFolderAndSelectItems(pidl, numFiles, (LPCITEMIDLIST *)files, 0);
|
||||
ILFree(pidl);
|
||||
for (uint32 i = 0; i < numFiles; i++)
|
||||
{
|
||||
ILFree(files[i]);
|
||||
}
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
// Return whether the dump was successful
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
static std::wstring GetDumpDirectory()
|
||||
{
|
||||
char userDirectory[MAX_PATH];
|
||||
platform_get_user_directory(userDirectory, NULL);
|
||||
|
||||
wchar_t * userDirectoryW = utf8_to_widechar(userDirectory);
|
||||
auto result = std::wstring(userDirectoryW);
|
||||
free(userDirectoryW);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_BREAKPAD
|
||||
|
||||
extern "C" CExceptionHandler newCExceptionHandlerSimple(void)
|
||||
// Using non-null pipe name here lets breakpad try setting OOP crash handling
|
||||
constexpr wchar_t * PipeName = L"openrct2-bpad";
|
||||
|
||||
extern "C" CExceptionHandler crash_init()
|
||||
{
|
||||
#ifdef USE_BREAKPAD
|
||||
char path[MAX_PATH];
|
||||
platform_get_user_directory(path, NULL);
|
||||
wchar_t *wpath_buffer = utf8_to_widechar(path);
|
||||
std::wstring wpath(wpath_buffer);
|
||||
free(wpath_buffer);
|
||||
// Path must exist and be RW!
|
||||
return reinterpret_cast<void*>(new google_breakpad::ExceptionHandler(
|
||||
wpath,
|
||||
0,
|
||||
dumpCallback,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
MiniDumpWithDataSegs,
|
||||
L"openrct2-bpad", // using non-null pipe name here lets breakpad try setting OOP crash handling
|
||||
0 ));
|
||||
// Path must exist and be RW!
|
||||
auto exHandler = new google_breakpad::ExceptionHandler(
|
||||
GetDumpDirectory(),
|
||||
0,
|
||||
OnCrash,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
MiniDumpWithDataSegs,
|
||||
PipeName,
|
||||
0);
|
||||
return reinterpret_cast<CExceptionHandler>(exHandler);
|
||||
#else // USE_BREAKPAD
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
#endif // USE_BREAKPAD
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#ifndef _OPENRCT2_CRASH_
|
||||
#define _OPENRCT2_CRASH_
|
||||
|
||||
typedef void* CExceptionHandler;
|
||||
typedef void * CExceptionHandler;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
CExceptionHandler newCExceptionHandlerSimple(void);
|
||||
CExceptionHandler crash_init();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue