Beefy Boxes and Bandwidth Generously Provided by pair Networks Russ
Think about Loose Coupling

comprehensive error handling

by mgibian (Acolyte)
on Jul 16, 2003 at 18:13 UTC ( #274965=perlquestion: print w/ replies, xml ) Need Help??
mgibian has asked for the wisdom of the Perl Monks concerning the following question:

This seems like such a fundamental question, but even though I've written thousands of lines of working Perl, I am quite puzzled by this issue.

I am writting a comprehensive set of scripts for building some software. Two features are that it must log comprehensively to a file anything of use in addition to providing some informative and progress messages to stdout; and, it must be very comprehensive in its error handling.

What has me puzzled is how one captures error information for many of the basic functions within Perl, and more specifically file related functions such as open, close, copy, unlink as a few examples. The common practice for these is to code up:

open(...) or die ".... $!"
My script needs to be more sophisticated in what it does in the error case than doing a simple die. I am guessing that I can put any code I need in the or case, but I have not seen any examples. Also, is the $! just a textual error message? I am thinking something like:
open (...) or { $errormsg = $!; $status = -1 }
or something similar would do the trick?

Anyone out there have any experience in doing more complete and rigorous error handling in Perl?

Comment on comprehensive error handling
Select or Download Code
Re: comprehensive error handling
by Aristotle (Chancellor) on Jul 16, 2003 at 18:30 UTC
    Use either simple parens and a single expression:
    open (...) or ($errormsg = $!, $status = -1);
    or expressify a block using do:
    open (...) or do { $errormsg = $!; $status = -1; }

    Makeshifts last the longest.

Re: comprehensive error handling
by blue_cowdawg (Prior) on Jul 16, 2003 at 18:44 UTC

    I should probably write a Perl Monk Meditation on this subject as it seems to be coming up a lot lately and I have had to deal with this in many ways over the years.

    CAVEAT:You will see some code here that has missing elements such as a lack of initialization and stuff like that. I am going to hand wave all of that so get over it.

    Opening files and such

    I tend to bury opening of files inside of OO modules and or subs and return the results unless the main purpose of the script is processing the file itself. (did that make sense?) For instance, here is a sniglet of code from a firewall log processor I wrote many many moons ago:

    # # code preceded this.... use vars qw @ $ip_pairs @; my $ip_pairs = undef; my ($result,$message)=open_traffic_log(); if ($result){ # recovery logic goes here.... } # # more code after that... exit(0); sub open_traffic_log() { if (! open("< fwlog.txt")){ return(0,$!); } # Process log file entries here. }

    That's one of many ways. Another approach that I use particulary within a CGI program.

    use CGI; use CGI::Carp qw / fatalsToBrowser /; # not in production! my $cgi= new CGI; # # stuff if ( not $cgi->param('paramIReallyNeed')){ logexeception('paramIReallyNeed was missing from page'); displayExeptionPage($cgi); # Won't return... displayExceptionPage exits. } # more code follows.
    With that approach I log the exception to a log file for debug purposes and the exception page actually tells the user "something really bad happened that shouldn't have and I have called for help."

    Useually though I just invoke either die or carp and move on appropriately.

    Other error handling

    There are other types of error handling that you need to consider as well. What about a failed fork() call or socket() call?

    I have sort of alluded to in a previous paragraph in this post but not spelled out the fact you also have to make the decision if a particular error is a fatal error and you need to stop execution or if it is a "soft" error that you can recover from programmatically.

    Peter L. BergholdBrewer of Belgian Ales
    Unix Professional
Re: comprehensive error handling
by dragonchild (Archbishop) on Jul 16, 2003 at 18:59 UTC
    use Error qw(:try); use Error::File; # This is something you write use IO::File; # Stuff here ... my $fh = try { IO::File->new($filename) || throw Error::File -text => $!; } catch Error::File with { my $err = shift; die "Cannot open file\n"; };
    Obviously, you would put more around this. I even have a where I have an Open() function. That will handle more common things, like filetest operators and filename checks and throw useful error messages. Of course, my errors are specific to my needs. YMMV

    We are the carpenters and bricklayers of the Information Age.



Re: comprehensive error handling (if)
by tye (Cardinal) on Jul 16, 2003 at 19:07 UTC

    There is also this little-known feature called if (or even unless). (:

    Trying to use the "or die" idiom for something that isn't as simple as "or die" is just a mistake, IMO.

    Though, they do have these things called subroutines... :)

                    - tye (yes, it is a small point. I wanted to make it.)
Re: comprehensive error handling
by adrianh (Chancellor) on Jul 16, 2003 at 19:38 UTC
Re: comprehensive error handling
by mgibian (Acolyte) on Jul 16, 2003 at 21:55 UTC
    Thank you everyone for your answers... they have been very helpful. I have already tried creating a method checkError and using the form:
    open(...) or $self->checkError(-1, "message with $!");
    I am using the method so that checkError has access to all of the methods for the class in its processing. This is a composite of a few of your suggestions and right now is addressing my current needs. For the long term, there is an attractiveness for using exceptions, though I am concerned by some of the comments I've read regarding limitations in the Perl exception mechanism.

      The only problem I've come across is the lack of direct syntax support. Once you get over seeing eval, die and if ($@) instead of try, throw and catch there shouldn't be any problems.

      But then, as you've probably guessed, I have a bias towards exception handling as a "good thing" :-)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://274965]
Approved by gjb
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (11)
As of 2014-03-17 18:23 GMT
Find Nodes?
    Voting Booth?

    Have you used a cryptocurrency?

    Results (355 votes), past polls