mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Add configurable error handlers.
The stackTrace and memContext error handlers were hard-coded which made testing the error module in isolation impossible. Making the error handlers configurable also makes adding new ones in the future easier.
This commit is contained in:
parent
8e9f04cc32
commit
5281e31422
@ -3,13 +3,13 @@ Error Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
|
@ -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
|
||||
***********************************************************************************************************************************/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user