mmlenz has asked for the wisdom of the Perl Monks concerning the following question:

We have a legacy web app that runs under ModPerl::RegistryPrefork and it works well. We use some code to log unhandled errors (that would result in a 500 response error). This code resides inside the modperl startup script and is something to the effect:
$SIG{__DIE__} = sub { my $error = shift; my $i = 0; my $caller = ''; while (my (undef,$file,$line,$sub) = caller($i++)) { $caller .= "Line $line of file $file called $sub\n"; } my $from_address = "blah@blah.com"; my $mailer = MIME::Lite->new( 'From' => $from_address, 'To' => $ENV{SERVER_ADMIN}, 'Subject' => 'ERROR on '. "$ENV{'SERVER_NAME'}", 'Data' => "When: ". scalar(localtime(time())). "\n\n". "Program: $ENV{SCRIPT_NAME}\n\n". "Error:\n$error\n". "Call Trace:\n$caller\n". "Environment Variables:\n". join("\n", map("$_ = $ENV{$_}", keys(%ENV))) ); $mailer->send_by_sendmail(SetSender => 1); }
Back when this code ran under modperl 1.x (many years ago) this worked great and we were only notified of actual system errors (500). It still works for modperl 2.x but we get a notification for EVERY exception in any code "use'd", not just system errors. I'd posted about this on a different forum sometime back and people came up with a few ideas with relation to checking return codes directly in apache2 mod perl or using a custom ErrorDocument 500 cgi and some ideas about using Perl*Handlers but the issue was that we couldn't see the call stack (which for obvious reasons is incredibly useful) for the code in question. I know this is probably too modperl/apache2 specific but I figured I'd try the monks :)

Replies are listed 'Best First'.
Re: grabbing un-handled exceptions via modperl2
by Anonymous Monk on May 03, 2013 at 20:44 UTC

    I think the safest way is to subclass whatever registry you're using ... but maybe you can borrow from ModPerl::RegistryCooker

    ###################################################################### +### # func: error_check # dflt: error_check # desc: checks $@ for errors # args: $self - registry blessed object # rtrn: Apache2::Const::SERVER_ERROR if $@ is set, Apache2::Const::OK +otherwise ###################################################################### +### sub error_check { my $self = shift; # ModPerl::Util::exit() throws an exception object whose rc is # ModPerl::EXIT # (see modperl_perl_exit() and modperl_errsv() C functions) if ($@ && !(ref $@ eq 'APR::Error' && $@ == ModPerl::EXIT)) { $self->log_error($@); return Apache2::Const::SERVER_ERROR; } return Apache2::Const::OK; }
      I just tried that ModPerl::RegistryPreforkCustom and the call trace isn't as complete which makes sense because I'd be checking it sooner.
      Line 207 of file /usr/lib/perl5/ModPerl/RegistryCooker.pm called ModPerl::RegistryPreforkCustom::error_check
      Line 170 of file /usr/lib/perl5/ModPerl/RegistryCooker.pm called ModPerl::RegistryCooker::run
      Line 19 of file /usr/lib/perl5/ModPerl/RegistryPrefork.pm called ModPerl::RegistryCooker::default_handler
      Line 0 of file -e called ModPerl::RegistryPrefork::handler
      Line 0 of file -e called (eval)
      
      vs ($SIG{DIE))
      
      Line 11 of file /home/mlenz/mlenz.domain.com/cgi-bin/details called main::__ANON__
      Line 204 of file /usr/lib/perl5/ModPerl/RegistryCooker.pm called ModPerl::ROOT::ModPerl::RegistryPreforkCustom::home_mlenz_mlenz_2edomain_2ecom_cgi_2dbin_details::handler
      Line 204 of file /usr/lib/perl5/ModPerl/RegistryCooker.pm called (eval)
      Line 170 of file /usr/lib/perl5/ModPerl/RegistryCooker.pm called ModPerl::RegistryCooker::run
      Line 19 of file /usr/lib/perl5/ModPerl/RegistryPrefork.pm called ModPerl::RegistryCooker::default_handler
      Line 0 of file -e called ModPerl::RegistryPrefork::handler
      Line 0 of file -e called (eval)
      
      Looks like I'd need to subclass the cooker instead and override one or more of the other methods.