Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: Re2: Learning how to use the Error module by example

by perrin (Chancellor)
on Jul 29, 2003 at 17:38 UTC ( #278900=note: print w/replies, xml ) Need Help??


in reply to Re2: Learning how to use the Error module by example
in thread Learning how to use the Error module by example

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.

Replies are listed 'Best First'.
Re4: Learning how to use the Error module by example
by dragonchild (Archbishop) on Jul 29, 2003 at 17:51 UTC
    Excellent! ++! Now, that explains what's going on. It's a little worrying that these examples are not in the Error documentation. A few thoughts:

    The first example, to me, is an example of how not to use try-catch. To me, you shouldn't be doing a return 0 within a catch. You should be rethrowing some error after doing what you needed to do. The only return statement should be as a result of success. Regardless of memory leaks, that's just poor practice.

    The second method ... the closure concern is a bit harsher for me. Matts does provide a solution for it, but I don't like it as it removes the major benefit imho, which is the syntactic sugar. I'll have to think about it and see whether it has a good workaround.

    ------
    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.

      The first example, to me, is an example of how not to use try-catch. To me, you shouldn't be doing a return 0 within a catch. You should be rethrowing some error after doing what you needed to do. The only return statement should be as a result of success. Regardless of memory leaks, that's just poor practice.

      I think that's a rather broad statement. Many people (myself included) think that multiple-returns can make code a lot clearer in some circumstances. For example, while you could rewrite this with a single return

      sub find { my ($self, $search_item) = @_; eval { # skip expensive search if item not stored anywhere return unless $search_item->stored; # otherwise do expensive search $self->first; while (my $item = $self->next) { return 1 if $item == $search_item; }; return; }; if ($@) { ... handle exceptions here ... }; };

      I would argue that it would be harder to grok than the version above.

      For me the main problem with Error is the fact that wrapping a bit of code in a catch block shouldn't change its semantics. This can lead to really odd behaviour when fiddling with exception based code.

        My point is that if you're wrapping in a try-block, you should be throwing exceptions, even something like Error::OK or the like. In fact, I wouldn't even call them exceptions, really. They're more like signals within the same process. Just because we use them 99.999% of the time to indicate an abnormal situation doesn't mean that this is what they should be limited to ...

        ------
        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.

      My return example is contrived, but there are situations where one might want to return from within a try block and it's counterintuitive to have to avoid it. This problem came up in the course of normal use. We were not looking for trouble.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://278900]
help
Chatterbox?
[LanX]: I'm willing to improve the code, but we have a götterdämmerung at the moment, Corion is the only active god for some time now
[moritz]: and everybody is like "if you just copy 250 lines of ugly JS into your free nodelet, and happent to know about it, there is a 40% that this workaround kinda works, sometimes"
[moritz]: ... "so there is no need to do anything"
[LanX]: and the code is a bit of a mess
[LanX]: moritz, no ... jsut copy one line of my code
[moritz]: I'm still using the CB, because ambrus's #cbstream makes it bearable
[LanX]: ... the rest is loaded from a node
[holli]: the best course of action would be to transfer the data to something well tested. even if it isnt perl based
[moritz]: but even if I had all the time in the world, I wouldn't spend much on perlmonks
[LanX]: holli: LOL

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (12)
As of 2017-11-20 19:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:













    Results (291 votes). Check out past polls.

    Notices?