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

Hi monks,

I'm wondering if there's a way to trap both fatal and non-fatal errors occurring in an entire module as it's being loaded by the calling script.

When'CGI::Carp qw(fatalsToBrowser)' is enabled, the error goes to the broswer, which is desirable during production development.

However, when 'CGI::Carp qw(fatalsToBrowser)' is disabled during production and an error occurs in one of the subs in the module, the script died with a '500 Internal Server Error'.

Is there a way to trap that error so that the unhelpful '500 Internal Server Error' can be prevented? Do you have to wrap each sub that's called with an 'eval' and then check for the value held in $@?

Thanks in advance!

Update: Edited the word 'production' to become 'development'. Thanks to dragonchild!

Replies are listed 'Best First'.
Re: Trap errors in entire module...
by matija (Priest) on Mar 28, 2004 at 09:27 UTC
    Given that your script is OK, and you're only looking for errors in other modules, you can put:
    BEGIN {use CGI::Carp qw(fatalsToBrowser);}
    as the first statement in your file, and they will go to the browser.

    I just tested putting this begin statement after the use call for the module with an error in it, and you only get erros in browser if the BEGIN is before the use.

      Thanks, matija!

      Is it possible to use 'warn' or a custom bail out subroutine there instead of 'use CGI::Carp qw(fatalsToBrowser);}?

        Naturally: there is nothing magical about CGI::Carp after all: look at it's code, and you'll see how it does it's work.

        Once you understand it, there should be no problem adapting it to your needs.

Re: Trap errors in entire module...
by dragonchild (Archbishop) on Mar 28, 2004 at 16:20 UTC
    When'CGI::Carp qw(fatalsToBrowser)' is enabled, the error goes to the broswer, which is desirable during production.

    No, No, NO, NO, NO! This is NEVER desirable in production for any reason at any time. Having this is production is a major security hole. Let's say the error is a SQL error ... now, you're displaying your database schema to the world. This means that I can craft a query to perform a SQL injection. And, that's just one of the millions of ways to break your site.

    Instead, it is much better to redefine the 500 handler as a script which displays a generic "There is a problem. Please contact management and let them know what you were doing". The error should be logged in some datastore (such as the error_log, if you're using Apache) and every page view should be logged, including user and parameters (which the access_log doesn't necessarily have), so that support staff can replicate what the user was doing at the time of the error.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Re: Trap errors in entire module...
by Anonymous Monk on Mar 29, 2004 at 14:14 UTC
    I use a CPAN module called Filter::Handle that might do what you're looking for.

    use Filter::Handle qw/subs/; # point STDERR to /dev/null, otherwise web server throws a 500 error i +f you print to STDERR, even with zero-ing out the output via () open(STDERR, ">/dev/null"); Filter \*STDERR, sub { fatal @_; #fatal is an internal sub to e-mail the devs () };

    The only problem with this approach is that it doesn't seem to Filter the STDERR output from other CPAN modules (say, HTML::Template) which is what I was trying to accomplish in the first place. Maybe someone more versed in Filter::Handle can explain that for me.