From 215b1b1aa4bb6deaf978ed2255643142886e4697 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 12 Feb 2016 03:32:42 +0100 Subject: [PATCH 1/2] On crash, takes minidump, then show MessageBox, and exit app. --- include/Game/MiniDump.h | 8 +++ src/Game/MiniDump.cpp | 106 ++++++++++++++++++++++++++++++++++++++++ src/Game/main.cpp | 22 +++++++-- 3 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 include/Game/MiniDump.h create mode 100644 src/Game/MiniDump.cpp diff --git a/include/Game/MiniDump.h b/include/Game/MiniDump.h new file mode 100644 index 00000000..4ad4548d --- /dev/null +++ b/include/Game/MiniDump.h @@ -0,0 +1,8 @@ +#ifndef MiniDump_h__ +#define MiniDump_h__ + +#include + +void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag); + +#endif diff --git a/src/Game/MiniDump.cpp b/src/Game/MiniDump.cpp new file mode 100644 index 00000000..0547e54e --- /dev/null +++ b/src/Game/MiniDump.cpp @@ -0,0 +1,106 @@ +/* + Author: Vladimir Sedach. + + Purpose: demo of Call Stack creation by our own means, + and with MiniDumpWriteDump() function of DbgHelp.dll. +*/ + +#include + +#include +#include +//#include "dbghelp.h" + +//#define DEBUG_DPRINTF 1 //allow d() +//#include "wfun.h" + +#pragma optimize("y", off) //generate stack frame pointers for all functions - same as /Oy- in the project +#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union +#pragma warning(disable: 4100) //unreferenced formal parameter + +// In case you don't have dbghelp.h. +#ifndef _DBGHELP_ + +typedef struct _MINIDUMP_EXCEPTION_INFORMATION { + DWORD ThreadId; + PEXCEPTION_POINTERS ExceptionPointers; + BOOL ClientPointers; +} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; + +typedef enum _MINIDUMP_TYPE { + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, +} MINIDUMP_TYPE; + +typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN PVOID UserStreamParam, OPTIONAL + IN PVOID CallbackParam OPTIONAL + ); + +#else + +typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL + IN PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL + ); +#endif //#ifndef _DBGHELP_ + +HMODULE hDbgHelp; +MINIDUMP_WRITE_DUMP MiniDumpWriteDump_; + +// Tool Help functions. +typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); + +//************************************************************************************* +void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag) +//************************************************************************************* +// Create dump. +// pException can be either GetExceptionInformation() or NULL. +// If File_Flag = TRUE - write dump files (.dmz and .dmp) with the name of the current process. +// If Show_Flag = TRUE - show message with Get_Exception_Info() dump. +{ + // Try to get MiniDumpWriteDump() address. + hDbgHelp = LoadLibrary("DBGHELP.DLL"); + MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); + + // If MiniDumpWriteDump() of DbgHelp.dll available. + if (MiniDumpWriteDump_) + { + HANDLE hDump_File; + CHAR Dump_Path[MAX_PATH]; + + GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); //path of current process + + MINIDUMP_EXCEPTION_INFORMATION M; + + M.ThreadId = GetCurrentThreadId(); + M.ExceptionPointers = pException; + M.ClientPointers = 0; + + lstrcpy(Dump_Path + lstrlen(Dump_Path) - 3, "dmp"); + + hDump_File = CreateFile(Dump_Path, + GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + MiniDumpWriteDump_(GetCurrentProcess(), GetCurrentProcessId(), hDump_File, + MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL); + + CloseHandle(hDump_File); + + std::cout << "Memory dumped to: \"" << Dump_Path << "\""; + MessageBox(NULL, ("Application crashed, memory dumped to: " + std::string(Dump_Path)).c_str(), "MiniDump", MB_ICONHAND | MB_OK); + } else { + MessageBox(NULL, "Application crashed, memory dump failed.", "MiniDump", MB_ICONHAND | MB_OK); + } +} + diff --git a/src/Game/main.cpp b/src/Game/main.cpp index 613165dd..dd2a5a84 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -1,11 +1,25 @@ #include "Game.h" +#include "MiniDump.h" + +LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException); int main(int argc, char* argv[]) { - Game game(argc, argv); - while (game.Running()) { - game.Tick(); - } + ::SetUnhandledExceptionFilter(CrashHandler); + + Game game(argc, argv); + while (game.Running()) { + game.Tick(); + } return 0; +} + +LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) +{ + //Take minidump. path should be bin/TacticalZ.dmp + //Then show MessageBox, and exit application. + Create_Dump(pException, 1, 1); + + return EXCEPTION_EXECUTE_HANDLER;// EXCEPTION_CONTINUE_SEARCH } \ No newline at end of file From 422bedb844c6f3dbbe18e4304270b2502cff95d3 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 12 Feb 2016 04:22:11 +0100 Subject: [PATCH 2/2] MiniDump name now depends on time e.g. TacticalZ Fri 04-20-49. --- src/Game/MiniDump.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Game/MiniDump.cpp b/src/Game/MiniDump.cpp index 0547e54e..bd8ee2de 100644 --- a/src/Game/MiniDump.cpp +++ b/src/Game/MiniDump.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -80,25 +81,28 @@ void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Sho CHAR Dump_Path[MAX_PATH]; GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); //path of current process + std::time_t t = std::time(NULL); + char tStr[16]; + std::strftime(tStr, 32, " %a %H-%M-%S", std::localtime(&t)); + std::string time(tStr); + std::string path(Dump_Path); + path = path.substr(0, path.length() - 4); + path += time + ".dmp"; MINIDUMP_EXCEPTION_INFORMATION M; - M.ThreadId = GetCurrentThreadId(); M.ExceptionPointers = pException; M.ClientPointers = 0; - lstrcpy(Dump_Path + lstrlen(Dump_Path) - 3, "dmp"); - - hDump_File = CreateFile(Dump_Path, - GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + hDump_File = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); MiniDumpWriteDump_(GetCurrentProcess(), GetCurrentProcessId(), hDump_File, MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL); CloseHandle(hDump_File); - std::cout << "Memory dumped to: \"" << Dump_Path << "\""; - MessageBox(NULL, ("Application crashed, memory dumped to: " + std::string(Dump_Path)).c_str(), "MiniDump", MB_ICONHAND | MB_OK); + std::cout << "Memory dumped to: \"" << path.c_str() << "\""; + MessageBox(NULL, ("Application crashed, memory dumped to: " + path).c_str(), "MiniDump", MB_ICONHAND | MB_OK); } else { MessageBox(NULL, "Application crashed, memory dump failed.", "MiniDump", MB_ICONHAND | MB_OK); }