I override dying in Perl for the FastCGI implementation of my code and include a test for $^S in the override:
$SIG{__DIE__} = sub {
return if $^S;
say STDERR 'Contents of $^S:' . $^S;
&SAFARI::Core::safariErrorLogWriter('Dying from error.'); };
}
sub safariErrorLogWriter {
my $message = shift;
return if $^S;
my ($file,$line,$id) = id(2);
return if ($file =~ /^\(eval/);
my $datestring = localtime();
my $ipAddress = ($ENV{'REMOTE_ADDR'} // 'Local') . ': ';
$message = $ipAddress . $datestring . ': ' . $message . '; At file: ' . $file . '; line: ' . $line . '; id: ' . $id . "\n";
state $moduleFileHomeDir = require File::HomeDir;
my $filePath = File::HomeDir->my_home . "/safari_error_log";
open(my $DATA,">>$filePath") || CORE::die "Couldn't open file file.txt, $!";
print $DATA $message;
close($DATA);
print STDERR $message;
}
The result in each case shows $^S as empty, as would be expected since the routine returns upon $^S being true.:
The result:
Local: Sat Jul 31 12:00:57 2021: Dying from error.; At file: /usr/local/lib64/perl5/CryptX.pm; line: 14; id:
However, during the normal course of loading modules return if ($file =~ /^\(eval/); is evaluated as true several times, seemingly indicating $^S is not giving the proper result. Several evals slip by both that test and $^S, for example, the one shown above when loading CryptX.pm, which is performing this eval on line 14:
eval { require Cpanel::JSON::XS }
Is there anything that would cause $^S to be inaccurate? Is there a better way to avoid getting evals in the mix here?
I tried to create a minimally reproducible example, but it doesn't seem to exhibit the same behavior, so there must be something else that is messing something up in the much larger code base. I guess that changes my question to: "What could alter the behavior such that $^S doesn't work as expected?
This works as expected:
#!/usr/bin/perl
Core::encodedSessionArray;
package Core;
$SIG{__DIE__} = sub { say STDERR "The result: " . $^S; return if $^S; &Core::safariErrorLogWriter('Dying from error.'); };
sub safariErrorLogWriter {
my $message = shift;
return if $^S;
my ($file,$line,$id) = id(2);
state $evalRegEx = qr#^\(eval#;
return if ($file =~ /$evalRegEx/);
my $datestring = localtime();
my $ipAddress = ($ENV{'REMOTE_ADDR'} // 'Local') . ': ';
$message = $ipAddress . $datestring . ': ' . $message . '; At file: ' . $file . '; line: ' . $line . '; id: ' . $id . "\n";
state $moduleFileHomeDir = require File::HomeDir;
my $filePath = File::HomeDir->my_home . "/safari_error_log";
open(my $DATA,">>$filePath") || CORE::die "Couldn't open file file.txt, $!";
print $DATA $message;
close($DATA);
print STDERR $message;
}
sub _makeIpKeyCryptObject {
my $ipAddress = $ENV{'REMOTE_ADDR'};
$ipAddress =~ s/\.//g;
# Make a 16 byte key out of the IP address info.
my $key = substr(sprintf("%016d", $ipAddress), 0, 16);
state $moduleCryptModeCBCEasy = require Crypt::Mode::CBC::Easy;
return Crypt::Mode::CBC::Easy->new(key => $key);
}
sub encodedSessionArray {
my $self = shift;
my $params = shift;
$params->{'sessionId'} = 0 unless $params->{'sessionId'};
$params->{'uid'} = '0' unless $params->{'uid'};
my $crypt = $self->_makeIpKeyCryptObject;
my $encrypted = $crypt->encrypt(($params->{'sessionId'}, $params->{'uid'},time()));
$encrypted =~ s/\n/\\n/g;
return $encrypted;
}
1;