minidump integration

This commit is contained in:
Ondrej Novak 2025-05-13 12:07:29 +02:00
parent 96eaeb4851
commit b459f2010e
9 changed files with 130 additions and 21 deletions

View file

@ -27,6 +27,7 @@ if(WIN32)
target_sources(skeldal_platform PRIVATE
windows/save_folder.cpp
windows/map_file.cpp
windows/minidump.cpp
)
add_executable(skeldal WIN32)
target_sources(skeldal PRIVATE

View file

@ -1,5 +1,6 @@
#include "legacy_coroutines.h"
#include "error.h"
#include "seh.h"
#include <thread>
#include <atomic>
@ -116,7 +117,7 @@ static void broadcast_message(EVENT_MSG *msg) {
clean_task_table();
}
static void crash_task_exception() {
/*static void crash_task_exception() {
try {
throw;
} catch (std::exception &e) {
@ -125,7 +126,7 @@ static void crash_task_exception() {
display_error("Unhandled exception in task %d: unknown/crash",q_current_task());
}
abort();
}
}*/
int add_task(int stack,TaskerFunctionName fcname,...) {
@ -135,14 +136,12 @@ int add_task(int stack,TaskerFunctionName fcname,...) {
va_list args;
va_start(args, fcname);
new_task->thr = std::thread([&]{
new_task->resume_flag.wait(false);
new_task->resume_flag = false;
try {
SEH_MONITOR_BEGIN {
new_task->resume_flag.wait(false);
new_task->resume_flag = false;
fcname(args);
clean_up_current_task();
} catch (...) {
crash_task_exception();
}
}SEH_MONITOR_END;
});
switch_to_task(new_task);
return id;

View file

@ -2,9 +2,11 @@
#include <stdint.h>
#include <stdio.h>
#ifndef _SKELDAL_PLATFORM_HEADER_
#define _SKELDAL_PLATFORM_HEADER_
#define BGSWITCHBIT 0x8000
#ifdef _MSC_VER
@ -124,6 +126,16 @@ typedef int (*LIST_FILES_CALLBACK)(const char *, LIST_FILE_TYPE , size_t, void *
int list_files(const char *directory, int type, LIST_FILES_CALLBACK cb, void *ctx);
#define WM_RELOADMAP (WM_APP+215)
#define E_RELOADMAP 40
typedef struct _ReloadMapInfo {
const char *fname;
int sektor;
} ReloadMapInfo;
#ifdef __cplusplus
}
#endif
@ -135,14 +147,4 @@ void init_joystick(const INI_CONFIG_SECTION *section);
char is_joystick_used();
char is_joystick_enabled();
#define WM_RELOADMAP (WM_APP+215)
#define E_RELOADMAP 40
typedef struct _ReloadMapInfo {
const char *fname;
int sektor;
} ReloadMapInfo;
#endif
#endif

10
platform/seh.h Normal file
View file

@ -0,0 +1,10 @@
#ifdef _WIN32
#include "windows/minidump.h"
#define SEH_MONITOR_BEGIN __try
#define SEH_MONITOR_END __except(GenerateMinidumpAndExit(GetExceptionInformation())) {}
#else
#define SEH_TRY
#define SEH_CATCH
#endif

View file

@ -2,6 +2,7 @@
#include "../getopt.h"
#include "../platform.h"
#include "../error.h"
#include "../seh.h"
#include <iostream>
#include <string>
#include <sstream>
@ -108,6 +109,10 @@ int __stdcall WinMain(HINSTANCE,HINSTANCE ,LPSTR, INT) {
argv[i][need-1] = 0;
}
GlobalFree(szArglist);
return main(argc, argv);
int r = -256;
SEH_MONITOR_BEGIN {
r = main(argc, argv);
} SEH_MONITOR_END;
return r;
}

View file

@ -0,0 +1,73 @@
#include "minidump.h"
#include <stdlib.h>
#include <wchar.h>
#include <version.h>
#include <dbghelp.h>
#pragma comment(lib, "dbghelp.lib")
DWORD WINAPI MessageBoxThread(LPVOID ptr) {
const wchar_t *txt = reinterpret_cast<const wchar_t *>(ptr);
return MessageBoxW(NULL, txt, L"SKELDAL", MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL|MB_APPLMODAL);
}
static void MessageBoxAndExit(const wchar_t *msg, const wchar_t *fname) {
DWORD tid;
HANDLE h = CreateThread(NULL, 0, MessageBoxThread, const_cast<wchar_t *>(msg), 0, &tid);
WaitForSingleObject(h, INFINITE);
if (fname != nullptr) {
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi;
wchar_t command[MAX_PATH + 20];
swprintf_s(command, L"explorer.exe /select,\"%s\"", fname);
if (CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
ExitProcess(256);
}
LONG WINAPI GenerateMinidumpAndExit(EXCEPTION_POINTERS* pExceptionInfo) {
wchar_t path[MAX_PATH];
_wfullpath(path, L"crash-" SKELDAL_VERSION ".dmp", _countof(path));
HANDLE hFile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) {
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pExceptionInfo;
mdei.ClientPointers = FALSE;
BOOL ret = MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
static_cast<MINIDUMP_TYPE>(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
&mdei,
NULL,
NULL);
CloseHandle(hFile);
if (ret) {
wchar_t msg[MAX_PATH*2];
swprintf_s(msg,L"Application crashed. The crash report has been stored to the file:\r\n\r\n%s\r\n\r\nPress OK to browse file in explorer",path);
MessageBoxAndExit(msg,path);
return 0;
}
}
{
DWORD error = GetLastError();
wchar_t msg[MAX_PATH*2];
swprintf_s(msg,L"Application crashed. Failed to write crash report to the file:\r\n\r\n%s\r\nError: %X", path, error);
MessageBoxAndExit(msg,path);
}
return 0;
}

View file

@ -0,0 +1,4 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
LONG WINAPI GenerateMinidumpAndExit(EXCEPTION_POINTERS* pExceptionInfo);