http://qs321.pair.com?node_id=226954

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

Fellow Monks,
I've grown accustomed to using CGI::Carp's fatalsToBrowser to help me with scripts.

To be frank, I work by trial and error, and I'd be lost without it.

But when does it not work? I've had scripts which fail and report the failure through fTB, and a moment later, another error will result in just 500 Internal Server Error and I have to go hunting through the httpd logs.

I'm not smart enough to figure out in which cases are caught by fTB and which ones aren't. Please enlighten me..?
--
“Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.” M-J D

Replies are listed 'Best First'.
Re: When Does FatalsToBrowser Not Send Fatals To Browser? (not die)
by tye (Sage) on Jan 14, 2003 at 22:38 UTC

    CGI::Carp's fatalsToBrowsers catches die. So it won't catch things that don't die nor things that die before it gets control (I think newer versions also catch warn and perhaps some other things, check the documentation source code for your version of the module for more details -- at least the documentation I noticed was quite vague).

    The second case is the easiest to categorize. If you have the statement use CGI::Carp 'fatalsToBrowser'; in your script, then CGI::Carp gets control as soon as that statement is done compiling. So compile-time errors in that statement or prior to it will not be caught. For example, #!/usr/bin/perl -wT might cause a "too late for -T" error that would not be caught. Not having CGI::Carp properly installed could also cause problems.

    There are a few ways to cause a server error without dieing so that they won't be caught. The following are some likely examples. Whether they actually cause a server error in spite of fatalsToBrowser may depend on the version of CGI::Carp you are using and on your web server configuration:

    • exit(1);
    • kill (perhaps by a watchdog that notes too much memory or CPU usage)
    • printing content that doesn't start with a valid CGI (content-type) header
    • printing something to STDERR

    What can go wrong before Perl gets control depends on your web server configuration. You could have a bad #! line (including having \r\n on the end when just \n was expected).

    (updated)

                    - tye
      For completeness: to see warnings, import warningsToBrowser. They will not be printed by default though - call warningsToBrowser(1); to enable and warningsToBrowser(0); to disable printing them. Output comes in the form of HTML comments. Note that warnings raised during disabled output don't get lost - they accumulate and get dumped the next time you enable output. I usually just put a warningsToBrowser(1); at the end of my script so that I get all the warnings in a neat pile at the bottom of my CGI generated page.

      Makeshifts last the longest.

Re: When Does FatalsToBrowser Not Send Fatals To Browser?
by bbfu (Curate) on Jan 14, 2003 at 22:18 UTC

    There are only 5 general cases where a "500 Internal Server Error" should be generated when you use CGI::Carp.

    1. The webserver experienced an error not actually caused by your script. This doesn't often happen, and isn't really related to your question.
    2. Something in your script printed some sort of garbage before CGI::Carp prints the necessary headers. I don't know that this would actually cause an ISE but it might, so I included it.
    3. The handler that CGI::Carp installs for $SIG{__DIE__} is not called for some reason. This could be because it has not yet been installed (some sort of syntax error before the use CGI::Carp ...; line has been compiled), or has been uninstalled or overwritten by some other piece of code.
    4. Some code sets $CGI::Carp::WRAP to a false value. This probably won't happen but, again, it is possible.
    5. Last minute addendum: Or, as dug points out, if some data has already been sent through mod_perl. This may be the same case as the second item I listed.

    Obviously, the most likely issue is that the handler was not called for some reason.

    Note that it is not called when inside an eval (well, it's called but just forwards the call onto realdie). That shouldn't matter, though, as the death will be trapped by the eval and, if it is propagated up, will be handled normally.

    You should always put the use CGI::Carp ...; line before including any other modules and before any actual code. This greatly reduces the likelyhood of the handler not being installed before an error is generated.

    There are ways to prevent (or trap) other code overwriting the $SIG{__DIE__} handler but it involves some possibly dicy magic and shouldn't be used in production code. You can see my Alarm::_TieSIG module to see how it would be done, and this discussion on why it is dicy.

    bbfu
    Black flowers blossum
    Fearless on my breath

Re: When Does FatalsToBrowser Not Send Fatals To Browser?
by dug (Chaplain) on Jan 14, 2003 at 21:49 UTC
    Are you using IE, perchance? Internet Explorer subverts some common error messages which can cause some real problems when debugging a web app.

    If you are using mod_perl, fatalsToBrowser checks $r->bytes_sent to determine whether it should simply use $r->print to display the fatal error or if it gets to set the status code and set the message. Here are the relavent bits from fatalsToBrowser:
    # If bytes have already been sent, then # we print the message out directly. # Otherwise we make a custom error # handler to produce the doc for us. if ($r->bytes_sent) { $r->print($mess); $r->exit; } else { $r->status(500); $r->custom_response(500,$mess); }

    -- dug
Re: When Does FatalsToBrowser Not Send Fatals To Browser?
by perrin (Chancellor) on Jan 14, 2003 at 22:11 UTC
    Oh, such a riddle! But think about it: it can't send anything to the browser if it doesn't run. It can't run if it doesn't compile. A syntax error that prevents your script from compiling will prevent fatalsToBrowser from working.
Re: When Does FatalsToBrowser Not Send Fatals To Browser?
by Cody Pendant (Prior) on Jan 15, 2003 at 03:23 UTC
    Thank you all very much for your help.

    It's much appreciated.

    The code that prompted this query, for the record, does compile, but fails when run for other reasons.
    --
    “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.” M-J D

Re: When Does FatalsToBrowser Not Send Fatals To Browser?
by zakzebrowski (Curate) on Jan 15, 2003 at 13:17 UTC
    FYI: One problem that I have run into is the non-standard location of perl. Thus, ensure that your #! line points to the correct location of perl. :)

    ----
    Zak
    Pluralitas non est ponenda sine neccesitate - mysql's philosphy
Re: When Does FatalsToBrowser Not Send Fatals To Browser?
by Anonymous Monk on Jan 15, 2003 at 21:30 UTC
    Or if perl segfaults or otherwise does 'something' that shouldn't happen. :)

    Casey