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 "build.auto.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/memContext.h"
|
|
||||||
#include "common/stackTrace.h"
|
#include "common/stackTrace.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@ -52,6 +52,10 @@ static struct
|
|||||||
// Array of jump buffers
|
// Array of jump buffers
|
||||||
jmp_buf jumpList[ERROR_TRY_MAX];
|
jmp_buf jumpList[ERROR_TRY_MAX];
|
||||||
|
|
||||||
|
// Handler list
|
||||||
|
const ErrorHandlerFunction *handlerList;
|
||||||
|
unsigned int handlerTotal;
|
||||||
|
|
||||||
// State of each try
|
// State of each try
|
||||||
int tryTotal;
|
int tryTotal;
|
||||||
|
|
||||||
@ -88,6 +92,15 @@ static char messageBuffer[ERROR_MESSAGE_BUFFER_SIZE];
|
|||||||
static char messageBufferTemp[ERROR_MESSAGE_BUFFER_SIZE];
|
static char messageBufferTemp[ERROR_MESSAGE_BUFFER_SIZE];
|
||||||
static char stackTraceBuffer[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
|
int
|
||||||
errorTypeCode(const ErrorType *errorType)
|
errorTypeCode(const ErrorType *errorType)
|
||||||
@ -312,8 +325,8 @@ errorInternalProcess(bool catch)
|
|||||||
// Else if just entering error state clean up the stack
|
// Else if just entering error state clean up the stack
|
||||||
else if (errorContext.tryList[errorContext.tryTotal].state == errorStateTry)
|
else if (errorContext.tryList[errorContext.tryTotal].state == errorStateTry)
|
||||||
{
|
{
|
||||||
stackTraceClean(errorTryDepth());
|
for (unsigned int handlerIdx = 0; handlerIdx < errorContext.handlerTotal; handlerIdx++)
|
||||||
memContextClean(errorTryDepth());
|
errorContext.handlerList[handlerIdx](errorTryDepth());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increment the state
|
// Increment the state
|
||||||
|
@ -110,11 +110,16 @@ const char *errorName(void);
|
|||||||
const char *errorStackTrace(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)
|
// Get the depth of the current try statement (0 if none)
|
||||||
unsigned int errorTryDepth(void);
|
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
|
Begin a block where errors can be thrown
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -42,6 +42,10 @@ Main
|
|||||||
int
|
int
|
||||||
main(int argListSize, const char *argList[])
|
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
|
#ifdef WITH_BACKTRACE
|
||||||
stackTraceInit(argList[0]);
|
stackTraceInit(argList[0]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,17 +50,19 @@ unit:
|
|||||||
- common/error.auto: noCode
|
- common/error.auto: noCode
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
- common/debug
|
|
||||||
- common/memContext
|
|
||||||
- common/stackTrace
|
- common/stackTrace
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------------------------------
|
||||||
- name: stack-trace
|
- name: stack-trace
|
||||||
total: 4
|
total: 4
|
||||||
|
feature: stackTrace
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
- common/stackTrace
|
- common/stackTrace
|
||||||
|
|
||||||
|
depend:
|
||||||
|
- common/debug
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------------------------------
|
||||||
- name: type-convert
|
- name: type-convert
|
||||||
total: 11
|
total: 11
|
||||||
|
@ -44,6 +44,17 @@ testTryRecurse(void)
|
|||||||
TRY_END();
|
TRY_END();
|
||||||
} // {uncoverable - function throws error, never returns}
|
} // {uncoverable - function throws error, never returns}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Test error handler
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
static unsigned int testErrorHandlerTryDepth;
|
||||||
|
|
||||||
|
static void
|
||||||
|
testErrorHandler(unsigned int tryDepth)
|
||||||
|
{
|
||||||
|
testErrorHandlerTryDepth = tryDepth;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Run
|
Test Run
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -103,6 +114,16 @@ testRun(void)
|
|||||||
volatile bool catchDone = false;
|
volatile bool catchDone = false;
|
||||||
volatile bool finallyDone = 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);
|
assert(errorTryDepth() == 0);
|
||||||
|
|
||||||
TRY_BEGIN()
|
TRY_BEGIN()
|
||||||
@ -131,6 +152,8 @@ testRun(void)
|
|||||||
}
|
}
|
||||||
CATCH(AssertError)
|
CATCH(AssertError)
|
||||||
{
|
{
|
||||||
|
assert(testErrorHandlerTryDepth == 3);
|
||||||
|
|
||||||
// Finally below should run even though this error has been rethrown
|
// Finally below should run even though this error has been rethrown
|
||||||
RETHROW();
|
RETHROW();
|
||||||
}
|
}
|
||||||
@ -142,6 +165,8 @@ testRun(void)
|
|||||||
}
|
}
|
||||||
CATCH_ANY()
|
CATCH_ANY()
|
||||||
{
|
{
|
||||||
|
assert(testErrorHandlerTryDepth == 2);
|
||||||
|
|
||||||
RETHROW();
|
RETHROW();
|
||||||
}
|
}
|
||||||
TRY_END();
|
TRY_END();
|
||||||
@ -152,6 +177,7 @@ testRun(void)
|
|||||||
}
|
}
|
||||||
CATCH(RuntimeError)
|
CATCH(RuntimeError)
|
||||||
{
|
{
|
||||||
|
assert(testErrorHandlerTryDepth == 1);
|
||||||
assert(errorTryDepth() == 1);
|
assert(errorTryDepth() == 1);
|
||||||
assert(errorContext.tryList[1].state == errorStateCatch);
|
assert(errorContext.tryList[1].state == errorStateCatch);
|
||||||
assert(strlen(errorMessage()) == sizeof(messageBuffer) - 1);
|
assert(strlen(errorMessage()) == sizeof(messageBuffer) - 1);
|
||||||
|
@ -61,6 +61,10 @@ Includes that are not generally used by tests
|
|||||||
#include "common/stat.h"
|
#include "common/stat.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HRN_IN_STACKTRACE
|
||||||
|
#include "common/stackTrace.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
main - run the tests
|
main - run the tests
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -85,6 +89,20 @@ main(int argListSize, const char *argList[])
|
|||||||
|
|
||||||
int result = 0;
|
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
|
// Initialize statistics
|
||||||
#if defined(HRN_INTEST_STAT) || defined(HRN_FEATURE_STAT)
|
#if defined(HRN_INTEST_STAT) || defined(HRN_FEATURE_STAT)
|
||||||
statInit();
|
statInit();
|
||||||
|
Loading…
Reference in New Issue
Block a user