- Naming style migrated to camel-case - P7lib logger sources added - Vcpkg manifest, CMake presets and build moved to root - SDL2, Vulkan and RmlUi dependencies added - Logger LOG macro added - Logger configuration - SDL2 window configuration - Vulkan configuration - RmlUi configuration - SDL event loop
294 lines
8.4 KiB
C
294 lines
8.4 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// 2012-2020 (c) Baical /
|
|
// /
|
|
// This library is free software; you can redistribute it and/or /
|
|
// modify it under the terms of the GNU Lesser General Public /
|
|
// License as published by the Free Software Foundation; either /
|
|
// version 3.0 of the License, or (at your option) any later version. /
|
|
// /
|
|
// This library is distributed in the hope that it will be useful, /
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
|
|
// Lesser General Public License for more details. /
|
|
// /
|
|
// You should have received a copy of the GNU Lesser General Public /
|
|
// License along with this library. /
|
|
// /
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus
|
|
|
|
#ifndef PSIGNAL_H
|
|
#define PSIGNAL_H
|
|
|
|
#include <new.h>
|
|
#include <crtdbg.h>
|
|
#include "signal.h"
|
|
#include "ISignal.h"
|
|
|
|
|
|
static stChContext g_stContext = {0};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChSignalHandler
|
|
static void __cdecl ChSignalHandler(int i_iSignal)
|
|
{
|
|
if (g_stContext.iProcessed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_stContext.iProcessed ++;
|
|
|
|
const char *l_pText = "unknown signal";
|
|
|
|
if (SIGABRT == i_iSignal)
|
|
{
|
|
l_pText = "SIGABRT";
|
|
}
|
|
else if (SIGFPE == i_iSignal)
|
|
{
|
|
l_pText = "SIGFPE";
|
|
}
|
|
else if (SIGILL == i_iSignal)
|
|
{
|
|
l_pText = "SIGILL";
|
|
}
|
|
else if (SIGINT == i_iSignal)
|
|
{
|
|
l_pText = "SIGINT";
|
|
}
|
|
else if (SIGSEGV == i_iSignal)
|
|
{
|
|
l_pText = "SIGSEGV";
|
|
}
|
|
else if (SIGTERM == i_iSignal)
|
|
{
|
|
l_pText = "SIGTERM";
|
|
}
|
|
|
|
|
|
if (g_stContext.pUserHandler)
|
|
{
|
|
g_stContext.pUserHandler((eCrashCode)(eCrashSignal + i_iSignal), l_pText, g_stContext.pUserContext);
|
|
}
|
|
|
|
exit(1);
|
|
}//ChSignalHandler
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChUnhandledExceptionFilter
|
|
static LONG WINAPI ChUnhandledExceptionFilter(__in struct _EXCEPTION_POINTERS *i_pException)
|
|
{
|
|
if (g_stContext.iProcessed)
|
|
{
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
if ( (STATUS_ACCESS_VIOLATION == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_ARRAY_BOUNDS_EXCEEDED == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_DATATYPE_MISALIGNMENT == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_FLT_DIVIDE_BY_ZERO == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_FLT_STACK_CHECK == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_ILLEGAL_INSTRUCTION == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_INT_DIVIDE_BY_ZERO == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_NONCONTINUABLE_EXCEPTION == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_PRIV_INSTRUCTION == i_pException->ExceptionRecord->ExceptionCode)
|
|
|| (EXCEPTION_STACK_OVERFLOW == i_pException->ExceptionRecord->ExceptionCode)
|
|
//|| ( == i_pException->ExceptionRecord.ExceptionCode)
|
|
)
|
|
{
|
|
g_stContext.iProcessed ++;
|
|
|
|
if (g_stContext.pUserHandler)
|
|
{
|
|
g_stContext.pUserHandler(eCrashException, i_pException, g_stContext.pUserContext);
|
|
}
|
|
|
|
exit(1);
|
|
}
|
|
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}//ChUnhandledExceptionFilter
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChPurecallHandler
|
|
static void ChPurecallHandler(void)
|
|
{
|
|
if (g_stContext.iProcessed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_stContext.iProcessed ++;
|
|
|
|
if (g_stContext.pUserHandler)
|
|
{
|
|
g_stContext.pUserHandler(eCrashPureCall, "Pure call", g_stContext.pUserContext);
|
|
}
|
|
|
|
exit(1);
|
|
}//ChPurecallHandler
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChMemoryAllocationHandler
|
|
static int ChMemoryAllocationHandler(size_t i_szSize)
|
|
{
|
|
if (g_stContext.iProcessed)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
g_stContext.iProcessed ++;
|
|
|
|
char l_pText[32];
|
|
|
|
sprintf_s(l_pText, "%lld", (tINT64)i_szSize);
|
|
|
|
if (g_stContext.pUserHandler)
|
|
{
|
|
g_stContext.pUserHandler(eCrashMemAlloc, l_pText, g_stContext.pUserContext);
|
|
}
|
|
|
|
exit(1);
|
|
|
|
return 0;
|
|
}//ChMemoryAllocationHandler
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChInvalidParameterHandler
|
|
static void ChInvalidParameterHandler(const wchar_t* i_pExpression,
|
|
const wchar_t* i_pFunction,
|
|
const wchar_t* i_pFile,
|
|
unsigned int i_dwLine,
|
|
uintptr_t i_pReserved
|
|
)
|
|
{
|
|
if (g_stContext.iProcessed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_stContext.iProcessed ++;
|
|
|
|
char l_pText[148];
|
|
const wchar_t *l_pFunction = i_pFunction ? i_pFunction : L"Func:Unk";
|
|
const wchar_t *l_pFile = i_pFile ? i_pFile : L"File:Unk";
|
|
size_t l_szFile = i_pFile ? wcslen(i_pFile) : 0;
|
|
size_t l_szFunc = i_pFunction ? wcslen(i_pFunction) : 0;
|
|
|
|
if ( l_szFile > 64 )
|
|
{
|
|
l_szFile -= 64;
|
|
}
|
|
|
|
if ( l_szFunc > 64 )
|
|
{
|
|
l_szFunc -= 64;
|
|
}
|
|
|
|
sprintf_s(l_pText, "{%S}{%S}{%d}", l_pFunction + l_szFunc, l_pFile + l_szFile, (int)i_dwLine);
|
|
|
|
if (g_stContext.pUserHandler)
|
|
{
|
|
g_stContext.pUserHandler(eCrashInvalidParameter, l_pText, g_stContext.pUserContext);
|
|
}
|
|
|
|
exit(1);
|
|
}//ChInvalidParameterHandler
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChInstallPrivate
|
|
static tBOOL ChInstallPrivate()
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//initialize handlers for all possible cases
|
|
signal(SIGABRT, ChSignalHandler);
|
|
signal(SIGFPE, ChSignalHandler);
|
|
signal(SIGILL, ChSignalHandler);
|
|
signal(SIGINT, ChSignalHandler);
|
|
signal(SIGSEGV, ChSignalHandler);
|
|
signal(SIGTERM, ChSignalHandler);
|
|
|
|
//SetUnhandledExceptionFilter(ChUnhandledExceptionFilter);
|
|
AddVectoredExceptionHandler(1, ChUnhandledExceptionFilter);
|
|
|
|
_set_purecall_handler(ChPurecallHandler);
|
|
|
|
_set_new_mode(1);
|
|
_set_new_handler(ChMemoryAllocationHandler);
|
|
|
|
_set_invalid_parameter_handler(ChInvalidParameterHandler);
|
|
|
|
_CrtSetReportMode(_CRT_ERROR, 0);
|
|
_CrtSetReportMode(_CRT_ASSERT, 0);
|
|
|
|
return TRUE;
|
|
}//ChInstallPrivate
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChInstall
|
|
static tBOOL ChInstall()
|
|
{
|
|
if (g_stContext.iInstalled)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//initialize parameters
|
|
memset(&g_stContext, 0, sizeof(g_stContext));
|
|
g_stContext.iInstalled = 1;
|
|
g_stContext.iProcessed = 0;
|
|
|
|
ChInstallPrivate();
|
|
|
|
return TRUE;
|
|
}//ChInstall
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChSetHandler
|
|
static tBOOL ChSetHandler(fnCrashHandler i_fnHandler)
|
|
{
|
|
if (!g_stContext.iInstalled)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
g_stContext.pUserHandler = i_fnHandler;
|
|
|
|
return TRUE;
|
|
}//ChSetHandler
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChSetContext
|
|
static tBOOL ChSetContext(void *i_pContext)
|
|
{
|
|
if (!g_stContext.iInstalled)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
g_stContext.pUserContext = i_pContext;
|
|
|
|
return TRUE;
|
|
}//ChSetContext
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//ChUnInstall
|
|
static tBOOL ChUnInstall()
|
|
{
|
|
return TRUE;
|
|
}//ChUnInstall
|
|
|
|
#endif //PSIGNAL_H
|