Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Learning how to use the Error module by example

by cleverett (Friar)
on Jul 28, 2003 at 21:09 UTC ( [id://278619]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I'm looking for modules that use the Error modules, so I can learn how to use it. The perldocs for it leave me a bit mystified. Though I have all kinds of modules on my system installed via CPAN, the only one that I grep out "use Error" from is DBI, and all it does with it is a single line "use Error;".

Replies are listed 'Best First'.
Re: Learning how to use the Error module by example
by perrin (Chancellor) on Jul 28, 2003 at 21:14 UTC
    I recommend that you don't use the try/catch syntax of the Error module. It can lead to some difficult bugs involving closures and returns that don't actually return.
      Please provide an example of where this situation occurs. If I didn't know you better, perrin, I would say that your statement is one of an ex-Java programmer waving his hands cause the try-catch syntax in Error reminds him of dark days in the past. :-)

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

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        I wouldn't just go spreading FUD abour Error.pm. It has very serious problems, and the only reason I didn't describe them is that I thought they were well-known. The try/catch syntax is implemented using sub ref prototypes. Take a look at this code:
        use Error qw( :try ); sub important_function { try { something_dangerous(); } catch Error::Simple with { return 0; }; return 1; }
        What value do you think this sub will return if it catches an error? It will always return 1, because the return inside of the catch block just returns from the implicit subroutine that the catch block creates. Nasty.

        Possibly worse, the nested closure problem can cause memory leaks in a long-running process. The problem is partially described by Matts in this presentation. Here's an example of a sub that will leak memory every time you call it:

        use Error qw( :try ); sub leaky_function { my $foo = 7; try { # do something here try { $foo++; } catch Error::Simple with { # whatever }; } catch Error::Simple with { # whatever }; }
        I hope I've got this code right; it's been a while since I used it.

        UPDATE: This leak seems to have been fixed in recent versions of Perl. That's a nice thing to see!

        We used Error in the system we built at eToys, and after having both of the problems I descibe here I have decided never to use the try/catch syntax again. It's dangerous and the problems are hard to see.

Re: Learning how to use the Error module by example
by broquaint (Abbot) on Jul 28, 2003 at 23:39 UTC
    Here's a little script I knocked up to test the capabilities of Error
    use Error qw( :try ); sub foo { warn "calling bar()\n"; bar(); } sub bar { throw Error::Simple("test error"); } sub evaltest { require Blah::Blah::Blah; Blah::Blah::Blah->new(); } sub run { warn "TEST 1\n"; try { warn "calling foo()\n"; foo(); warn "foo called()\n"; } catch Error::Simple with { my $E = shift; warn "Caught error: $E"; }; warn "TEST 2\n"; try { warn "calling evaltest()\n"; evaltest(); } catch Error::Simple with { warn "Caught error: $_[0]\n"; }; try { throw Error::Simple("except me"); } except { return { Error => sub { warn "whoa: $_[0]\n" }, 'Error::Simple' => sub { warn "wah: $_[0]" }, }; }; warn "\nTesting done\n"; } main->run();
    Essentially it'll catch anything that an eval block will and I've generally found it'll DTRT :)
    HTH

    _________
    broquaint

Re: Learning how to use the Error module by example
by dragonchild (Archbishop) on Jul 29, 2003 at 12:29 UTC
    I use Error in my personal scripty-doos at work (it's actually a bunch of modules for my personal consumption) and it works really well. You have to create a bunch of Error classes that will describe the type of error you are trapping on. This is because Error deals with the class of the error and makes decisions based on that.

    Here's what I do with DBI (for instance}:

    # Within some connect_to_db() function ... my $dbh = try { DBI->connect( $conn_string, $props{USER}, $props{PWD}, { PrintError => 0, RaiseError => 1, }, ) } otherwise { throw Error::Database -text => ( $DBI::errstr || $@ || "Unknown Error: '$conn_string'" ); }; $dbh->{HandleError} = sub { throw Error::Database -text => $DBI::er +rstr }; return $dbh; } # Now, any DB action I take that would ordinarily return undef # will now throw an Error::Database. As long as all my DB # activity is within a try-catch area, I'm fine. :-) # Within another section, I have: my ($dbh, $fh); try { my ($properties, $datafile) = Parameter::Validate(@ARGV, 2); $dbh = Database::Connect(File::ReadProperties($properties)); my %db_values = Retrieve_DB_Values($dbh); $fh = File::Open( $datafile, mode => 'w', ); # Do more stuff here } catch Error::Simple with { my ($err, $recover) = @_; throw Error::Unknown -text => $err->text; } catch Error with { my ($err, $recover) = @_; die $err->text . $/; } otherwise { throw Error::Unknown -text => $@; } finally { Database::Disconnect($dbh); File::Close($fh); };
    Note that I have wrapped around DBI->connect and IO::File->new, in order to provide consistent error handling.

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

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Learning how to use the Error module by example
by cleverett (Friar) on Jul 28, 2003 at 21:21 UTC
    Hmm, is there something similarly useful, or should I just use eval?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://278619]
Approved by derby
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (2)
As of 2025-04-18 03:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.