Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I catch and rethrow an error in Perl?

Tags:

perl

Let's say I have a module Bar that is a subclass wrapper for module Foo. I want calls to Bar's methods to mimic Foo's exactly -- even down to fatal errors. So far, easy enough; I just call the SUPER method.


sub stuff {
    # Do stuff here

    SUPER::stuff(@_);

    # Do more stuff here
}

But, let's say that I want to catch, log, and rethrow any fatal errors SUPER::stuff() produces. First two steps are easy:


sub stuff {
    # Do stuff here

    eval {
        SUPER::stuff(@_);
    };
    $@ and log("Naughty, naughty: $@");

    # Do more stuff here
}

... but I don't know how to do the last part. How do I re-throw the error in such a way that the caller will be unable to distinguish between a call to Foo->stuff() and a call to Bar->stuff()? Can I just insert die $@ after the log statement and expect it to do what I want, or are there nuances here that would likely get me into trouble?

like image 238
BlairHippo Avatar asked Feb 24 '23 06:02

BlairHippo


1 Answers

The full code to safely eval/catch/log/rethrow in Perl can be a bit verbose.

sub stuff {
    # Do stuff here

    local $@; # don't reset $@ for our caller.
    my $eval_ok = eval { # get the return from eval, it will be undef if the eval catches an error.
        SUPER::stuff(@_);
        1; # return 1 (true) if there are no errors caught.
    };
    if (!$eval_ok) { # don't trust $@ it might have been reset as the eval unrolled.
        my $error = $@ || 'unknown error'; # copy $@ incase write_log resets $@, or is later changed to cause it to reset $@.
        write_log("Naughty, naughty: $error");
        die $error; # after all that we can rethrow our error.
    }

    # Do more stuff here
}

You can use Try::Tiny sugested by mob to simplify:

sub stuff {
    # Do stuff here

    try {
        SUPER::stuff(@_);
    } catch {
        my $error = $_;
        write_log("Naughty, naughty: $error");
        die $error;
    }

    # Do more stuff here
}
like image 135
Ven'Tatsu Avatar answered Mar 02 '23 23:03

Ven'Tatsu