diff --git a/src/common/error.c b/src/common/error.c index f0c0dba1b..b168c66a2 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -3,13 +3,13 @@ Error Handler ***********************************************************************************************************************************/ #include "build.auto.h" +#include #include #include #include #include #include "common/error.h" -#include "common/memContext.h" #include "common/stackTrace.h" /*********************************************************************************************************************************** @@ -52,6 +52,10 @@ static struct // Array of jump buffers jmp_buf jumpList[ERROR_TRY_MAX]; + // Handler list + const ErrorHandlerFunction *handlerList; + unsigned int handlerTotal; + // State of each try int tryTotal; @@ -88,6 +92,15 @@ static char messageBuffer[ERROR_MESSAGE_BUFFER_SIZE]; static char messageBufferTemp[ERROR_MESSAGE_BUFFER_SIZE]; static char stackTraceBuffer[ERROR_MESSAGE_BUFFER_SIZE]; +/**********************************************************************************************************************************/ +void errorHandlerSet(ErrorHandlerFunction *list, unsigned int total) +{ + assert(total == 0 || list != NULL); + + errorContext.handlerList = list; + errorContext.handlerTotal = total; +} + /**********************************************************************************************************************************/ int errorTypeCode(const ErrorType *errorType) @@ -312,8 +325,8 @@ errorInternalProcess(bool catch) // Else if just entering error state clean up the stack else if (errorContext.tryList[errorContext.tryTotal].state == errorStateTry) { - stackTraceClean(errorTryDepth()); - memContextClean(errorTryDepth()); + for (unsigned int handlerIdx = 0; handlerIdx < errorContext.handlerTotal; handlerIdx++) + errorContext.handlerList[handlerIdx](errorTryDepth()); } // Increment the state diff --git a/src/common/error.h b/src/common/error.h index 0c0dc0600..d23ac8e35 100644 --- a/src/common/error.h +++ b/src/common/error.h @@ -110,11 +110,16 @@ const char *errorName(void); const char *errorStackTrace(void); /*********************************************************************************************************************************** -Functions to get information about the try stack +Try stack getters/setters ***********************************************************************************************************************************/ // Get the depth of the current try statement (0 if none) unsigned int errorTryDepth(void); +// Add a handler to be called when an error occurs +typedef void (*const ErrorHandlerFunction)(unsigned int); + +void errorHandlerSet(const ErrorHandlerFunction *list, unsigned int total); + /*********************************************************************************************************************************** Begin a block where errors can be thrown ***********************************************************************************************************************************/ diff --git a/src/main.c b/src/main.c index edfa83388..de015f682 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,10 @@ Main int main(int argListSize, const char *argList[]) { + // Set stack trace and mem context error cleanup handlers + static const ErrorHandlerFunction errorHandlerList[] = {stackTraceClean, memContextClean}; + errorHandlerSet(errorHandlerList, sizeof(errorHandlerList) / sizeof(ErrorHandlerFunction)); + #ifdef WITH_BACKTRACE stackTraceInit(argList[0]); #endif diff --git a/test/define.yaml b/test/define.yaml index a53990ed2..b63738cc6 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -50,17 +50,19 @@ unit: - common/error.auto: noCode depend: - - common/debug - - common/memContext - common/stackTrace # ---------------------------------------------------------------------------------------------------------------------------- - name: stack-trace total: 4 + feature: stackTrace coverage: - common/stackTrace + depend: + - common/debug + # ---------------------------------------------------------------------------------------------------------------------------- - name: type-convert total: 11 diff --git a/test/src/module/common/errorTest.c b/test/src/module/common/errorTest.c index aee2eaf4f..7c66288b6 100644 --- a/test/src/module/common/errorTest.c +++ b/test/src/module/common/errorTest.c @@ -44,6 +44,17 @@ testTryRecurse(void) TRY_END(); } // {uncoverable - function throws error, never returns} +/*********************************************************************************************************************************** +Test error handler +***********************************************************************************************************************************/ +static unsigned int testErrorHandlerTryDepth; + +static void +testErrorHandler(unsigned int tryDepth) +{ + testErrorHandlerTryDepth = tryDepth; +} + /*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ @@ -103,6 +114,16 @@ testRun(void) volatile bool catchDone = false; volatile bool finallyDone = false; + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("set error handler"); + + static const ErrorHandlerFunction testErrorHandlerList[] = {testErrorHandler}; + errorHandlerSet(testErrorHandlerList, sizeof(testErrorHandlerList) / sizeof(ErrorHandlerFunction)); + + assert(errorContext.handlerList[0] == testErrorHandler); + assert(errorContext.handlerTotal == 1); + + // ------------------------------------------------------------------------------------------------------------------------- assert(errorTryDepth() == 0); TRY_BEGIN() @@ -131,6 +152,8 @@ testRun(void) } CATCH(AssertError) { + assert(testErrorHandlerTryDepth == 3); + // Finally below should run even though this error has been rethrown RETHROW(); } @@ -142,6 +165,8 @@ testRun(void) } CATCH_ANY() { + assert(testErrorHandlerTryDepth == 2); + RETHROW(); } TRY_END(); @@ -152,6 +177,7 @@ testRun(void) } CATCH(RuntimeError) { + assert(testErrorHandlerTryDepth == 1); assert(errorTryDepth() == 1); assert(errorContext.tryList[1].state == errorStateCatch); assert(strlen(errorMessage()) == sizeof(messageBuffer) - 1); diff --git a/test/src/test.c b/test/src/test.c index 07842417d..8ebb086bd 100644 --- a/test/src/test.c +++ b/test/src/test.c @@ -61,6 +61,10 @@ Includes that are not generally used by tests #include "common/stat.h" #endif +#ifdef HRN_IN_STACKTRACE + #include "common/stackTrace.h" +#endif + /*********************************************************************************************************************************** main - run the tests ***********************************************************************************************************************************/ @@ -85,6 +89,20 @@ main(int argListSize, const char *argList[]) int result = 0; +#ifdef HRN_FEATURE_ERROR + static const ErrorHandlerFunction handlerList[] = + { +#if defined(HRN_INTEST_STACKTRACE) || defined(HRN_FEATURE_STACKTRACE) + stackTraceClean, +#endif +#if defined(HRN_INTEST_MEMCONTEXT) || defined(HRN_FEATURE_MEMCONTEXT) + memContextClean, +#endif + }; + + errorHandlerSet(handlerList, sizeof(handlerList) / sizeof(ErrorHandlerFunction)); +#endif + // Initialize statistics #if defined(HRN_INTEST_STAT) || defined(HRN_FEATURE_STAT) statInit();