Perl global error handler

This is in an Apache::ASP based system, but should theoretically work in any web environment.

I wanted to create a global default error handler ($SIG{__DIE__}) that displays the error text on the page.

Some notes:

  • It is generally recommended that run-time errors be trapped on a case-by-case basis using try/catch style eval statements.
  • A global handler may be triggered erroneously by eval statements that you or any library you use might execute this way.
  • It is generally recommended that compile-time errors be handled by an ErrorDocument instead of a signal trap.
  • An error handler triggered by compile-time errors may be running in a precarious state – and might therefore itself fail.
  • It is generally expected that errors be logged in Apache’s error log (ie, via STDERR).
  • An error handler that traps an error, may erroneously return a success (200 OK) status code.
  • Returning a more appropriate error code triggers Apache’s error handling mechanism (ErrorDocument), overriding any custom output.

It is easy enough to create an error handler that emails errors (in addition to logging them), but the coup de gras would be displaying them as well.  Per the above, there are a few obstacles to overcome.  Note that it wouldn’t be a good idea to do this in a production environment, but it could be handy in a development system.

My solution uses the following principals:

  • To be eval safe, the error handler avoids doing anything beyond benign variable modification.
  • The Apache ErrorDocument mechanism is used so as to make trapping compile-time errors safe.
  • This way, the return status code is not modified either.
  • Usually ErrorDocument can only be used to display a generic error message, but by passing data via CGI environment variables, custom output can be achieved.

This is the error handler:

use Carp;
local $SIG{__DIE__} = sub { $ENV{ERROR} = Carp::longmess ( @_ ); };

The ErrorDocument.asp code:

<%
  use CGI;
  if ( exists ( $ENV{REDIRECT_ERROR} ) )
    { print "<pre>" . CGI::escapeHTML ( $ENV{REDIRECT_ERROR} ) . "</pre>"; }
  else
    { $::Response->{Status} = 500; }
%>

Notice that $ENV{ERROR} in the error handler is $ENV{REDIRECT_ERROR} in ErrorDocument.asp.
Configure Apache to use the custom ErrorDocument:

ErrorDocument 500 "<path>/ErrorDocument.asp"

You can add code to send an email as well.
Note: Additional code such as this should go in the ErrorDocument.asp file – the error handler should be kept to an absolute minimum. This is because compile-time errors create a precarious state in which any call to “use strict” (ie, any well written library) will kill the handler. It’s possible to get around this with an eval.

Leave a Reply

Your email address will not be published. Required fields are marked *