1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-04-25 12:04:48 +02:00
David Steele 79cfd3aebf Remove LibC.
This was the interface between Perl and C introduced in 36a5349b but since f0ef73db has only been used by the Perl integration tests.  This is expensive code to maintain just for testing.

The main dependency was the interface to storage, no matter where it was located, e.g. S3.  Replace this with the new-introduced repo commands (d3c83453) that allow access to repo storage via the command line.

The other dependency was on various cfgOption* functions and CFGOPT_ constants that were convenient but not necessary.  Replace these with hard-coded strings in most places and create new constants for commonly used values.

Remove all auto-generated Perl code.  This means that the error list will no longer be maintained automatically so copy used errors to Common::Exception.pm.  This file will need to be maintained manually going forward but there is not likely to be much churn as the Perl integration tests are being retired.

Update test.pl and related code to remove LibC builds.

Ding, dong, LibC is dead.
2020-03-09 17:41:59 -04:00

193 lines
6.6 KiB
Perl

####################################################################################################################################
# Process Execution, Management, and IO
####################################################################################################################################
package pgBackRest::Common::Io::Process;
use parent 'pgBackRest::Common::Io::Filter';
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use Exporter qw(import);
our @EXPORT = qw();
use IPC::Open3 qw(open3);
use POSIX qw(:sys_wait_h);
use Symbol 'gensym';
use pgBackRest::Common::Exception;
use pgBackRest::Common::Io::Buffered;
use pgBackRest::Common::Log;
use pgBackRest::Common::Wait;
####################################################################################################################################
# Amount of time to attempt to retrieve errors when a process terminates unexpectedly
####################################################################################################################################
use constant IO_ERROR_TIMEOUT => 5;
####################################################################################################################################
# new - use open3 to run the command and get the io handles
####################################################################################################################################
sub new
{
my $class = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParent,
$strCommand,
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'oParent', trace => true},
{name => 'strCommand', trace => true},
);
# Bless with new class
my $self = $class->SUPER::new($oParent);
bless $self, $class;
# Use open3 to run the command
my ($iProcessId, $fhRead, $fhWrite, $fhReadError);
$fhReadError = gensym;
$iProcessId = IPC::Open3::open3($fhWrite, $fhRead, $fhReadError, $strCommand);
# Set handles
$self->handleReadSet($fhRead);
$self->handleWriteSet($fhWrite);
# Set variables
$self->{iProcessId} = $iProcessId;
$self->{fhReadError} = $fhReadError;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self}
);
}
####################################################################################################################################
# error - handle errors
####################################################################################################################################
sub error
{
my $self = shift;
my $iCode = shift;
my $strMessage = shift;
my $strDetail = shift;
my $bClose = shift;
if (defined($self->{iProcessId}))
{
my $oWait = waitInit(defined($iCode) ? IO_ERROR_TIMEOUT : 0);
do
{
# Check the result
my $iResult = waitpid($self->{iProcessId}, $bClose ? 0 : WNOHANG);
# Error if the process exited unexpectedly
if ($iResult != 0)
{
# Get the exit status
$self->{iExitStatus} = $iResult == -1 ? 255 : ${^CHILD_ERROR_NATIVE} >> 8;
# Drain the stderr stream
my $strError;
my $oIoError = new pgBackRest::Common::Io::Buffered(
new pgBackRest::Common::Io::Handle($self->id(), $self->{fhReadError}), 5, $self->bufferMax());
while (defined(my $strLine = $oIoError->readLine(true, false)))
{
$strError .= (defined($strError) ? "\n" : '') . $strLine;
}
delete($self->{iProcessId});
if ((!$bClose && $self->{iExitStatus} != 0) || defined($strError))
{
my $iErrorCode =
$self->{iExitStatus} >= ERROR_MINIMUM && $self->{iExitStatus} <= ERROR_MAXIMUM ?
$self->{iExitStatus} : ERROR_FILE_READ;
logErrorResult(
$iErrorCode, $self->id() . ' terminated unexpectedly' .
($self->{iExitStatus} != 255 ? sprintf(' [%03d]', $self->{iExitStatus}) : ''),
$strError);
}
}
}
while (waitMore($oWait));
if (defined($iCode))
{
$self->parent()->error($iCode, $strMessage, $strDetail);
}
}
else
{
confess &log(ASSERT, 'cannot call error() after process has been closed');
}
}
####################################################################################################################################
# Get process id
####################################################################################################################################
sub processId
{
my $self = shift;
return $self->{iProcessId};
}
####################################################################################################################################
# Get exit status (after close() is called)
####################################################################################################################################
sub exitStatus
{
my $self = shift;
return $self->{iExitStatus};
}
####################################################################################################################################
# writeLine - check for error before writing line
####################################################################################################################################
sub writeLine
{
my $self = shift;
my $strBuffer = shift;
# Check if the process has exited abnormally (doesn't seem like we should need this, but the next syswrite does a hard
# abort if the remote process has already closed)
$self->error();
return $self->parent()->writeLine($strBuffer);
}
####################################################################################################################################
# close - check if the process terminated on error
####################################################################################################################################
sub close
{
my $self = shift;
if (defined($self->{iProcessId}))
{
$self->error(undef, undef, undef, true);
# Class parent close
$self->parent()->close();
}
return true;
}
1;