//////////////////////////////////////////////////////////////////////////////// // / // 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 #include #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