mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
5afd950ed9
The prior code used TRY...CATCH blocks to cleanup mem contexts when an error occurred. This included freeing new mem contexts that were still being initialized when the error occurred and ensuring that the prior memory context was restored. This worked fine in production but it involved a lot of setjmp()/longjmp() calls that resulted in longer compilation times and sluggish performance under valgrind, profiling, and coverage testing. Instead maintain a stack of new contexts and context switches that can be used to do cleanup after an error. Normally, the stack is not used for this purpose and pushing/popping is a cheap operation. In the prior implementation most of the TRY...CATCH logic needed to be run even on success. One bonus is that the binary is about 8% smaller after this change. Another benefit is that new contexts *must* be explicitly freed/discarded or an error will occur. See info/manifest.c for an example of where this is useful outside the standard macros.
79 lines
7.6 KiB
C
79 lines
7.6 KiB
C
/***********************************************************************************************************************************
|
|
Helper macros for LibC.xs
|
|
***********************************************************************************************************************************/
|
|
|
|
/***********************************************************************************************************************************
|
|
Package Names
|
|
***********************************************************************************************************************************/
|
|
#define PACKAGE_NAME "pgBackRest"
|
|
#define PACKAGE_NAME_LIBC PACKAGE_NAME "::LibC"
|
|
|
|
/***********************************************************************************************************************************
|
|
Error handling macros that throw a Perl error when a C error is caught
|
|
***********************************************************************************************************************************/
|
|
#define ERROR_XS_BEGIN() \
|
|
TRY_BEGIN()
|
|
|
|
#define ERROR_XS() \
|
|
croak("PGBRCLIB:%d:%s:%d:%s", errorCode(), errorFileName(), errorFileLine(), errorMessage());
|
|
|
|
#define ERROR_XS_END() \
|
|
CATCH_ANY() \
|
|
{ \
|
|
ERROR_XS(); \
|
|
} \
|
|
TRY_END();
|
|
|
|
/***********************************************************************************************************************************
|
|
Simplifies switching to a temp memory context in functions and includes error handling
|
|
***********************************************************************************************************************************/
|
|
#define MEM_CONTEXT_XS_TEMP() \
|
|
MEM_CONTEXT_XS_TEMP_memContext
|
|
|
|
#define MEM_CONTEXT_XS_TEMP_BEGIN() \
|
|
{ \
|
|
/* Create temp memory context */ \
|
|
MemContext *MEM_CONTEXT_XS_TEMP() = memContextNew("temporary"); \
|
|
\
|
|
/* Switch to temp memory context */ \
|
|
memContextSwitch(MEM_CONTEXT_XS_TEMP()); \
|
|
\
|
|
/* Store any errors to be croaked to Perl at the end */ \
|
|
bool MEM_CONTEXT_XS_croak = false; \
|
|
\
|
|
/* Try the statement block */ \
|
|
TRY_BEGIN()
|
|
|
|
#define MEM_CONTEXT_XS_TEMP_END() \
|
|
/* Set error to be croak to Perl later */ \
|
|
CATCH_ANY() \
|
|
{ \
|
|
MEM_CONTEXT_XS_croak = true; \
|
|
} \
|
|
/* Free the context on error */ \
|
|
FINALLY() \
|
|
{ \
|
|
memContextSwitchBack(); \
|
|
memContextDiscard(); \
|
|
} \
|
|
TRY_END(); \
|
|
\
|
|
/* Croak on error */ \
|
|
if (MEM_CONTEXT_XS_croak) \
|
|
{ \
|
|
ERROR_XS() \
|
|
} \
|
|
}
|
|
|
|
/***********************************************************************************************************************************
|
|
Create new string from an SV
|
|
***********************************************************************************************************************************/
|
|
#define STR_NEW_SV(param) \
|
|
(SvOK(param) ? strNewN(SvPV_nolen(param), SvCUR(param)) : NULL)
|
|
|
|
/***********************************************************************************************************************************
|
|
Create const buffer from an SV
|
|
***********************************************************************************************************************************/
|
|
#define BUF_CONST_SV(param) \
|
|
(SvOK(param) ? BUF(SvPV_nolen(param), SvCUR(param)) : NULL)
|