eqemu-server/common/crash.cpp

118 lines
3.4 KiB
C++

#include "debug.h"
#include "eqemu_logsys.h"
#include "crash.h"
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
#include "StackWalker.h"
class EQEmuStackWalker : public StackWalker
{
public:
EQEmuStackWalker() : StackWalker() { }
EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { }
virtual void OnOutput(LPCSTR szText) {
char buffer[4096];
for(int i = 0; i < 4096; ++i) {
if(szText[i] == 0) {
buffer[i] = '\0';
break;
}
if(szText[i] == '\n' || szText[i] == '\r') {
buffer[i] = ' ';
} else {
buffer[i] = szText[i];
}
}
logger.Log(EQEmuLogSys::Crash, buffer);
StackWalker::OnOutput(szText);
}
};
LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
{
switch(ExceptionInfo->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_ACCESS_VIOLATION");
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
break;
case EXCEPTION_BREAKPOINT:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_BREAKPOINT");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_DATATYPE_MISALIGNMENT");
break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_DENORMAL_OPERAND");
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_DIVIDE_BY_ZERO");
break;
case EXCEPTION_FLT_INEXACT_RESULT:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_INEXACT_RESULT");
break;
case EXCEPTION_FLT_INVALID_OPERATION:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_INVALID_OPERATION");
break;
case EXCEPTION_FLT_OVERFLOW:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_OVERFLOW");
break;
case EXCEPTION_FLT_STACK_CHECK:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_STACK_CHECK");
break;
case EXCEPTION_FLT_UNDERFLOW:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_FLT_UNDERFLOW");
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_ILLEGAL_INSTRUCTION");
break;
case EXCEPTION_IN_PAGE_ERROR:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_IN_PAGE_ERROR");
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_INT_DIVIDE_BY_ZERO");
break;
case EXCEPTION_INT_OVERFLOW:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_INT_OVERFLOW");
break;
case EXCEPTION_INVALID_DISPOSITION:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_INVALID_DISPOSITION");
break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_NONCONTINUABLE_EXCEPTION");
break;
case EXCEPTION_PRIV_INSTRUCTION:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_PRIV_INSTRUCTION");
break;
case EXCEPTION_SINGLE_STEP:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_SINGLE_STEP");
break;
case EXCEPTION_STACK_OVERFLOW:
logger.Log(EQEmuLogSys::Crash, "EXCEPTION_STACK_OVERFLOW");
break;
default:
logger.Log(EQEmuLogSys::Crash, "Unknown Exception");
break;
}
if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
{
EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord);
}
return EXCEPTION_EXECUTE_HANDLER;
}
void set_exception_handler() {
SetUnhandledExceptionFilter(windows_exception_handler);
}
#else
// crash is off or an unhandled platform
void set_exception_handler() {
}
#endif