2
votes

Thanks to everyone in advance.

I've been doing some research on error handling and I don't feel like I'm getting a solid understanding of what I should do.

Preamble: My code is living in Apache and executed in the browser, my goals don't include command line execution.

I'd like to have the behavior of CGI::Carp (fatalsToBrowser) with the ability to capture the output and be able to throw it in my own templated page, email it etc... I did notice that fatalsToBrowser doesn't work with mod_perl. Does anyone know why? How is Apache/mod_perl getting in the way?


First Goal: I'd like to put something together that works if the code is being executed with mod_perl or mod_cgi.

Second Goal: I'd like to have a high-level method(s) that catches all the errors similar to .NET's Application_Error (in global.asax) and PHP's set_exception_handler() and set_error_handler() methods. These allow you to take control when an error is raised, without wrapping code in messy/gross try-catch statements.


Things I've read/reviewed:

1.) OO Exception Handling in Perl, but wasn't what I was looking for. Most of the stuff I want to catch is die()ing. The next link also says that this article is out of date and deprecated.

2.) Perl: $SIG{__DIE__}, eval { } and stack trace, but I didn't get much from this related to my goals.

3.) Practical Mode Perl (O'Reilly), Chapter 21 "Error Handling and Debugging". Thankfully all my perl code uses strict and warnings are enabled, and most important things mentioned in Chapter 6 "Coding with mod_perl in Mind" are already done.

4.) I've dug through the tables of contents in "Learning Perl", "Perl Cookbook", "Programming Perl" and "Higher Order Perl" and didn't see anything that stuck out at me. If you think I missed something there please let me know. :)


I don't remember where (maybe in "Practical mod_perl", but I've read that you should not mess with $SIG{__DIE__}.

2
Are your scripts real mod_perl scripts or are you just running CGI scripts as ModPerl::Registry scripts for the performance advantage?Sinan Ünür
My scripts will (should) perform the same in either environment.rakhavan
I think you should re-evaluate your opinion on try/catch blocks. They are not at all messy or gross if used at the right level.innaM
@Manni, I use try/catch blocks like that in other code... like I said in my OP, the second goal is "high-level" trapping. Thanks for your replies.rakhavan

2 Answers

1
votes

Have you read the mod_perl website's bit on Alternative Exception Handling Techniques? It discusses about how you can catch uncaught exceptions though the use of overriding the global die() function instead of using $SIG{__DIE__}. A much cleaner method but not perfect.

1
votes

What type of errors are you trying to catch? Are custom error pages not sufficient for your purposes?

My CGI scripts are short (OK, this is really bare bones — and untested):

#!/usr/bin/perl

use strict;
use warnings;

use My::App;
use My::ErrorReporter qw( error_to_html );

run();

sub run {
    my $app = eval {
        My::App->new(
            'some_param',
            'another_param',
        )
    };

    unless ( $app ) {
        print error_to_html( $@ );
        return;
    }

    eval {
        $app->handle_request;        
    } and return;

    print error_to_html( $@ );
    return;
}

__END__

Now, fatalsToBrowser is not for your users. That is a development aid for you. The error messages users see should not convey information about the program. So, for example, in a routine that opens and reads a configuration file, you should do something like:

sub read_my_config {
    my $self = shift;

    open my $config_h, '<', $self->config_file;

    unless ( $config_h ) {
        # This goes to the Apache error log where you can read it
        warn sprintf(
            "Cannot open '%s': %s", 
            $self->config_file, $!
        );
        # This is for web site visitors to see
        die "Cannot open configuration file";
    }

    # rest of the code
}