From c278df081f0078f7617a10a4cc41818baff2c156 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 14 Jun 2013 14:33:02 +0200 Subject: [PATCH] Create minidump file if FreeCAD crashes on Windows --- src/Main/MainGui.cpp | 106 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index 03407c52d6..fdb417da2c 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -161,6 +161,10 @@ private: QDomDocument domDocument; }; +#if defined(_MSC_VER) +void InitMiniDumpWriter(const std::string&); +#endif + #if defined (FC_OS_LINUX) || defined(FC_OS_BSD) QString myDecoderFunc(const QByteArray &localFileName) { @@ -224,6 +228,12 @@ int main( int argc, char ** argv ) // Inits the Application App::Application::init(argc,argv); +#if defined(_MSC_VER) + // create a dump file when the application crashes + std::string dmpfile = App::Application::getUserAppDataDir(); + dmpfile += "crash.dmp"; + InitMiniDumpWriter(dmpfile); +#endif Gui::Application::initApplication(); Base::Interpreter().replaceStdOutput(); } @@ -325,3 +335,99 @@ int main( int argc, char ** argv ) return 0; } + +#if defined(_MSC_VER) +#include +#include + +typedef BOOL (__stdcall *tMDWD)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL + IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL + ); + +static tMDWD s_pMDWD; +static HMODULE s_hDbgHelpMod; +static MINIDUMP_TYPE s_dumpTyp = MiniDumpNormal; +static std::string s_szMiniDumpFileName; // initialize with whatever appropriate... + +static LONG __stdcall MyCrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx) +{ +#ifdef _M_IX86 + if (pEx->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) + { + // be sure that we have enought space... + static char MyStack[1024*128]; + // it assumes that DS and SS are the same!!! (this is the case for Win32) + // change the stack only if the selectors are the same (this is the case for Win32) + //__asm push offset MyStack[1024*128]; + //__asm pop esp; + __asm mov eax,offset MyStack[1024*128]; + __asm mov esp,eax; + } +#endif + bool bFailed = true; + HANDLE hFile; + hFile = CreateFile(s_szMiniDumpFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + MINIDUMP_EXCEPTION_INFORMATION stMDEI; + stMDEI.ThreadId = GetCurrentThreadId(); + stMDEI.ExceptionPointers = pEx; + stMDEI.ClientPointers = TRUE; + // try to create an miniDump: + if (s_pMDWD( + GetCurrentProcess(), + GetCurrentProcessId(), + hFile, + s_dumpTyp, + &stMDEI, + NULL, + NULL + )) + { + bFailed = false; // suceeded + } + CloseHandle(hFile); + } + + if (bFailed) + { + return EXCEPTION_CONTINUE_SEARCH; + } + + // Optional display an error message + // FatalAppExit(-1, ("Application failed!")); + + + // or return one of the following: + // - EXCEPTION_CONTINUE_SEARCH + // - EXCEPTION_CONTINUE_EXECUTION + // - EXCEPTION_EXECUTE_HANDLER + return EXCEPTION_CONTINUE_SEARCH; // this will trigger the "normal" OS error-dialog +} + +void InitMiniDumpWriter(const std::string& filename) +{ + if (s_hDbgHelpMod != NULL) + return; + s_szMiniDumpFileName = filename; + + // Initialize the member, so we do not load the dll after the exception has occured + // which might be not possible anymore... + s_hDbgHelpMod = LoadLibrary(("dbghelp.dll")); + if (s_hDbgHelpMod != NULL) + s_pMDWD = (tMDWD) GetProcAddress(s_hDbgHelpMod, "MiniDumpWriteDump"); + + // Register Unhandled Exception-Filter: + SetUnhandledExceptionFilter(MyCrashHandlerExceptionFilter); + + // Additional call "PreventSetUnhandledExceptionFilter"... + // See also: "SetUnhandledExceptionFilter" and VC8 (and later) + // http://blog.kalmbachnet.de/?postid=75 +} +#endif