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


I have a situation where I want control to return to the main script when an error occurs in an object. There the main script can decide how to deal with the error.

I have been enclosing object creation and method calls in the eval{...}; if ($@) {...} technique.

1.) Main creates Object A.

2.) Object A creates Object B.

3.) Object B creates Object C.

4.) An error occurs in Object C and Object C dies.

5.) Object B catches the error and logs it and dies.

6.) Control returns to Object A, but before Object A can test the $@ value the destructors for Object C and Object B are called in that order. The calls to the destructors wipe out the $@ value and Object A continues without processing the error in its "if ($@) {} block".


How can I improve my design here? Is it a bad practice to catch an error and then call die again?

There seem to be many approaches to the art of error handling. I am not sure of the best practice here. If an error occurs in Object C, I would like to destroy the chain of objects A-B-C, log their errors, and return to Main to process the error.

Replies are listed 'Best First'.
Re: Error Handling in Object-Oriented Perl
by lestrrat (Deacon) on May 23, 2002 at 21:57 UTC

    How does your $@ get reset in your destructor? ( I assume you're talking about DESTROY() )

    If it's just a simple matter of $@ being reset because of something you do in DESTROY, I think this is all you need (which is similar to what I recently experienced):

    sub DESTROY { local $@; ... your cleanup code... }

    If not, I think we would need more context...


      Thank you for your quick assistance, lestrrat! Adding local $@; in the destructors protected the $@ value from being reset. I was making logging calls in the destructors which were resetting $@.

      I still, however, have lingering questions about best practices for error handling in this circumstance. Is the practice of calling die in the if ($@) {...} block good practice?

      I, also, have open-ended issues about comingling error handling and logging. For instance, calling die if $self->fatal("error message"); is called.

        I don't know about best practices, but I do this all the time...

        eval { ... } if( my $err = $@ ) { die $err; }

        However, I tend to make my code propagate most of fatal errors all the way up to the user, unless there is some compelling reason that the error must be trapped in that particular level. I trap and re-throw in mostly in cases when I want to add more logging information than $@ would otherwise contain... otherwise I just let it propagate.

        ... and since that "compelling reason" varies from application to application, I don't have a general solution :(