You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-05-22 10:15:16 +02:00
Perl error handler recognizes errors thrown from the C library.
This commit is contained in:
+1
-1
@@ -336,7 +336,7 @@ eval
|
|||||||
or do
|
or do
|
||||||
{
|
{
|
||||||
# If a backrest exception then return the code
|
# If a backrest exception then return the code
|
||||||
exit $EVAL_ERROR->code() if (isException($EVAL_ERROR));
|
exit $EVAL_ERROR->code() if (isException(\$EVAL_ERROR));
|
||||||
|
|
||||||
# Else output the unhandled error
|
# Else output the unhandled error
|
||||||
print $EVAL_ERROR;
|
print $EVAL_ERROR;
|
||||||
|
|||||||
+1
-1
@@ -196,7 +196,7 @@ eval
|
|||||||
or do
|
or do
|
||||||
{
|
{
|
||||||
# If a backrest exception then return the code
|
# If a backrest exception then return the code
|
||||||
exit $EVAL_ERROR->code() if (isException($EVAL_ERROR));
|
exit $EVAL_ERROR->code() if (isException(\$EVAL_ERROR));
|
||||||
|
|
||||||
# Else output the unhandled error
|
# Else output the unhandled error
|
||||||
print $EVAL_ERROR;
|
print $EVAL_ERROR;
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
<release-item>
|
<release-item>
|
||||||
<p>Add C error handler.</p>
|
<p>Add C error handler.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<p>Perl error handler recognizes errors thrown from the C library.</p>
|
||||||
|
</release-item>
|
||||||
</release-refactor-list>
|
</release-refactor-list>
|
||||||
</release-core-list>
|
</release-core-list>
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ sub new
|
|||||||
{
|
{
|
||||||
# Capture error information
|
# Capture error information
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($iResult != 0)
|
if ($iResult != 0)
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ sub new
|
|||||||
{
|
{
|
||||||
# Capture error information
|
# Capture error information
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($iResult != 0)
|
if ($iResult != 0)
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ sub process
|
|||||||
{
|
{
|
||||||
# Capture error information
|
# Capture error information
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
|
|
||||||
# Check archive.info
|
# Check archive.info
|
||||||
@@ -104,7 +104,7 @@ sub process
|
|||||||
{
|
{
|
||||||
# Capture error information
|
# Capture error information
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ sub process
|
|||||||
{
|
{
|
||||||
# Capture error information
|
# Capture error information
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,15 +248,32 @@ sub trace
|
|||||||
}
|
}
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# isException
|
# isException - is this a structured exception or a default Perl exception?
|
||||||
#
|
|
||||||
# Is this a structured exception?
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
sub isException
|
sub isException
|
||||||
{
|
{
|
||||||
my $oException = shift;
|
my $roException = shift;
|
||||||
|
|
||||||
return defined($oException) && blessed($oException) && $oException->isa('pgBackRest::Common::Exception') ? 1 : 0;
|
# Only check if defined
|
||||||
|
if (defined($roException) && defined($$roException))
|
||||||
|
{
|
||||||
|
# If a standard Exception
|
||||||
|
if (blessed($$roException))
|
||||||
|
{
|
||||||
|
return $$roException->isa('pgBackRest::Common::Exception') ? 1 : 0;
|
||||||
|
}
|
||||||
|
# Else if a specially formatted string from the C library
|
||||||
|
elsif ($$roException =~ /^PGBRCLIB\:[0-9]+\:/)
|
||||||
|
{
|
||||||
|
my @stryException = split(/\:/, $$roException);
|
||||||
|
$$roException = new pgBackRest::Common::Exception(
|
||||||
|
"ERROR", $stryException[1] + 0, $stryException[4], $stryException[2] . qw{:} . $stryException[3]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
push @EXPORT, qw(isException);
|
push @EXPORT, qw(isException);
|
||||||
@@ -270,7 +287,7 @@ sub exceptionCode
|
|||||||
{
|
{
|
||||||
my $oException = shift;
|
my $oException = shift;
|
||||||
|
|
||||||
return isException($oException) ? $oException->code() : ERROR_UNKNOWN;
|
return isException(\$oException) ? $oException->code() : ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
push @EXPORT, qw(exceptionCode);
|
push @EXPORT, qw(exceptionCode);
|
||||||
@@ -284,7 +301,7 @@ sub exceptionMessage
|
|||||||
{
|
{
|
||||||
my $oException = shift;
|
my $oException = shift;
|
||||||
|
|
||||||
return isException($oException) ? $oException->message() : $oException;
|
return isException(\$oException) ? $oException->message() : $oException;
|
||||||
}
|
}
|
||||||
|
|
||||||
push @EXPORT, qw(exceptionMessage);
|
push @EXPORT, qw(exceptionMessage);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ sub exitSafe
|
|||||||
if (!defined($iExitCode))
|
if (!defined($iExitCode))
|
||||||
{
|
{
|
||||||
# If a backrest exception
|
# If a backrest exception
|
||||||
if (isException($oException))
|
if (isException(\$oException))
|
||||||
{
|
{
|
||||||
$iExitCode = $oException->code();
|
$iExitCode = $oException->code();
|
||||||
logException($oException);
|
logException($oException);
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ sub errorWrite
|
|||||||
my $oException = shift;
|
my $oException = shift;
|
||||||
|
|
||||||
# Throw hard error if this is not a standard exception
|
# Throw hard error if this is not a standard exception
|
||||||
if (!isException($oException))
|
if (!isException(\$oException))
|
||||||
{
|
{
|
||||||
confess &log(ERROR, 'unknown error: ' . $oException, ERROR_UNKNOWN);
|
confess &log(ERROR, 'unknown error: ' . $oException, ERROR_UNKNOWN);
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ sub process
|
|||||||
logLevelSet(undef, undef, PROTOCOL);
|
logLevelSet(undef, undef, PROTOCOL);
|
||||||
|
|
||||||
# If standard exception
|
# If standard exception
|
||||||
if (isException($oException))
|
if (isException(\$oException))
|
||||||
{
|
{
|
||||||
confess &log($oException->level(), $oException->message(), $oException->code());
|
confess &log($oException->level(), $oException->message(), $oException->code());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ sub close
|
|||||||
my $strError = 'unable to shutdown protocol';
|
my $strError = 'unable to shutdown protocol';
|
||||||
my $strHint = 'HINT: the process completed all operations successfully but protocol-timeout may need to be increased.';
|
my $strHint = 'HINT: the process completed all operations successfully but protocol-timeout may need to be increased.';
|
||||||
|
|
||||||
if (isException($oException))
|
if (isException(\$oException))
|
||||||
{
|
{
|
||||||
$iExitStatus = $oException->code();
|
$iExitStatus = $oException->code();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ sub process
|
|||||||
my $oException = $EVAL_ERROR;
|
my $oException = $EVAL_ERROR;
|
||||||
|
|
||||||
# If not a backrest exception then always confess it - something has gone very wrong
|
# If not a backrest exception then always confess it - something has gone very wrong
|
||||||
confess $oException if (!isException($oException));
|
confess $oException if (!isException(\$oException));
|
||||||
|
|
||||||
# If the process is has terminated throw the exception
|
# If the process is has terminated throw the exception
|
||||||
if (!defined($hLocal->{oLocal}->io()->processId()))
|
if (!defined($hLocal->{oLocal}->io()->processId()))
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ sub infoObject
|
|||||||
# Reset console logging and capture error information
|
# Reset console logging and capture error information
|
||||||
logEnable();
|
logEnable();
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($iResult != 0)
|
if ($iResult != 0)
|
||||||
@@ -445,7 +445,7 @@ sub infoFileCreate
|
|||||||
# Reset console logging and capture error information
|
# Reset console logging and capture error information
|
||||||
logEnable();
|
logEnable();
|
||||||
$iResult = exceptionCode($EVAL_ERROR);
|
$iResult = exceptionCode($EVAL_ERROR);
|
||||||
$strResultMessage = exceptionMessage($EVAL_ERROR->message());
|
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||||
};
|
};
|
||||||
|
|
||||||
# If we got here without error then save the reconstructed file
|
# If we got here without error then save the reconstructed file
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Helper macros for LibC.xs
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Package Names
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define PACKAGE_NAME "pgBackRest"
|
||||||
|
#define PACKAGE_NAME_LIBC PACKAGE_NAME "::LibC"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Load C error into ERROR_SV_error
|
||||||
|
|
||||||
|
#define FUNCTION_NAME_ERROR "libcExceptionNew"
|
||||||
|
|
||||||
|
#define ERROR_SV() \
|
||||||
|
SV *ERROR_SV_error; \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
// Push parameters onto the Perl stack \
|
||||||
|
ENTER; \
|
||||||
|
SAVETMPS; \
|
||||||
|
PUSHMARK(SP); \
|
||||||
|
EXTEND(SP, 2); \
|
||||||
|
PUSHs(sv_2mortal(newSViv(errorCode()))); \
|
||||||
|
PUSHs(sv_2mortal(newSVpv(errorMessage(), 0))); \
|
||||||
|
PUTBACK; \
|
||||||
|
\
|
||||||
|
// Call error function \
|
||||||
|
int count = call_pv(PACKAGE_NAME_LIBC "::" FUNCTION_NAME_ERROR, G_SCALAR); \
|
||||||
|
SPAGAIN; \
|
||||||
|
\
|
||||||
|
// Check that correct number of parameters was returned \
|
||||||
|
if (count != 1) \
|
||||||
|
croak("expected 1 return value from " FUNCTION_NAME_ERROR "()"); \
|
||||||
|
\
|
||||||
|
// Make a copy of the error that can be returned \
|
||||||
|
ERROR_SV_error = newSVsv(POPs); \
|
||||||
|
\
|
||||||
|
// Clean up the stack \
|
||||||
|
PUTBACK; \
|
||||||
|
FREETMPS; \
|
||||||
|
LEAVE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
This turned out to be a dead end because Perl 5.10 does not support croak_sv(), but this code has been kept for example purposes.
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Error handling macros that throw a Perl error when a C error is caught
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define ERROR_XS_BEGIN() \
|
||||||
|
ERROR_TRY()
|
||||||
|
|
||||||
|
#define ERROR_XS() \
|
||||||
|
croak("PGBRCLIB:%d:%s:%d:%s", errorCode(), errorFileName(), errorFileLine(), errorMessage());
|
||||||
|
|
||||||
|
#define ERROR_XS_END() \
|
||||||
|
ERROR_CATCH_ANY() \
|
||||||
|
{ \
|
||||||
|
ERROR_XS(); \
|
||||||
|
}
|
||||||
+5
-1
@@ -26,11 +26,15 @@ C includes
|
|||||||
These includes are from the src directory. There is no Perl-specific code in them.
|
These includes are from the src directory. There is no Perl-specific code in them.
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/type.h"
|
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "config/configRule.h"
|
#include "config/configRule.h"
|
||||||
#include "postgres/pageChecksum.h"
|
#include "postgres/pageChecksum.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Helper macros
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#include "LibC.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Constant include
|
Constant include
|
||||||
|
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ sub testResult
|
|||||||
# Restore the log level
|
# Restore the log level
|
||||||
logLevelSet($strLogLevelFile, $strLogLevelConsole, $strLogLevelStdErr, $bLogTimestamp);
|
logLevelSet($strLogLevelFile, $strLogLevelConsole, $strLogLevelStdErr, $bLogTimestamp);
|
||||||
|
|
||||||
if (!isException($EVAL_ERROR))
|
if (!isException(\$EVAL_ERROR))
|
||||||
{
|
{
|
||||||
confess "unexpected standard Perl exception" . (defined($EVAL_ERROR) ? ": ${EVAL_ERROR}" : '');
|
confess "unexpected standard Perl exception" . (defined($EVAL_ERROR) ? ": ${EVAL_ERROR}" : '');
|
||||||
}
|
}
|
||||||
@@ -421,7 +421,7 @@ sub testException
|
|||||||
{
|
{
|
||||||
logEnable();
|
logEnable();
|
||||||
|
|
||||||
if (!isException($EVAL_ERROR))
|
if (!isException(\$EVAL_ERROR))
|
||||||
{
|
{
|
||||||
confess "${strError} but actual was standard Perl exception" . (defined($EVAL_ERROR) ? ": ${EVAL_ERROR}" : '');
|
confess "${strError} but actual was standard Perl exception" . (defined($EVAL_ERROR) ? ": ${EVAL_ERROR}" : '');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ sub configTestLoadExpect
|
|||||||
|
|
||||||
$bErrorFound = true;
|
$bErrorFound = true;
|
||||||
|
|
||||||
if (isException($oException))
|
if (isException(\$oException))
|
||||||
{
|
{
|
||||||
if ($oException->code() != $iExpectedError)
|
if ($oException->code() != $iExpectedError)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -968,7 +968,7 @@ eval
|
|||||||
or do
|
or do
|
||||||
{
|
{
|
||||||
# If a backrest exception then return the code
|
# If a backrest exception then return the code
|
||||||
exit $EVAL_ERROR->code() if (isException($EVAL_ERROR));
|
exit $EVAL_ERROR->code() if (isException(\$EVAL_ERROR));
|
||||||
|
|
||||||
# Else output the unhandled error
|
# Else output the unhandled error
|
||||||
syswrite(*STDOUT, $EVAL_ERROR);
|
syswrite(*STDOUT, $EVAL_ERROR);
|
||||||
|
|||||||
+1
-1
@@ -181,7 +181,7 @@ eval
|
|||||||
or do
|
or do
|
||||||
{
|
{
|
||||||
# If a backrest exception then return the code
|
# If a backrest exception then return the code
|
||||||
exit $EVAL_ERROR->code() if (isException($EVAL_ERROR));
|
exit $EVAL_ERROR->code() if (isException(\$EVAL_ERROR));
|
||||||
|
|
||||||
# Else output the unhandled error
|
# Else output the unhandled error
|
||||||
print $EVAL_ERROR;
|
print $EVAL_ERROR;
|
||||||
|
|||||||
Reference in New Issue
Block a user