Create minidump file if FreeCAD crashes on Windows

This commit is contained in:
wmayer
2013-06-14 14:33:02 +02:00
parent 9c39be0aca
commit c278df081f

View File

@@ -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 <windows.h>
#include <dbghelp.h>
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