During an eval block, how do I trap errors originating only in that piece of code and not from some code that was called from withing that block? The following snippet can fail because $code_ref isn't defined/can't be looked up or because something inside $code_ref threw an error.
eval { $function_name->(); }; if ( my $e = $@ ) { # Just pretend that __FILE__ interpolates. if ( $e =~ /Undefined subroutine .+ called at if ( $e =~ /Unde +fined subroutine .+ called at __FILE__ line 2\./ ) { # Trap only this one error ... } else { # Rethrow the error die $e; } }
Perl only gives me a string to parse with a file and line number. Got a better way? Has anyone done anything nice with source filters or similar to tag the inside of eval blocks with #line "..." ... compiler directives to aid with the identification of errors from within specific blocks? There is a parallel problem of how to identify specific errors. I'm not as worried about that because that seems more tractable. The strings perl throws aren't as mutable or potentially strange as the file/line part I already identified; I can generally get away with expecting "Undefined subroutine" to remain constant.
Added: I am currently trying the following in AI::Prolog/Engine/Primitives.pm but it is ugly as sin and I don't want to have to do this in the general case.
use constant UNDEFINED_SUBROUTINE_ERROR => do { eval { no strict 'refs'; ## no critic NoStrict &{'---'}; }; my $e = $@; # Undefined subroutine &main::--- called at .../Primitives.pm line + 12. my ($msg) = $e =~ / \A (.+) # 'Undefined subroutine' (?<=\s) # ' ' \S* # &main:: ---/mx or die q[Perl's error message changed! Damn! Fix this regex.]; $msg; }; sub ... { ... # If the error is that I couldn't call the # function because it didn't exist or AUTOLOAD wouldn't DWIM then # I want to return fail. # # I want to avoid Class::Delegation's misfeature of eating all # non-related errors while it traps for the few things that it # needs. if ( my $e = $@ ) { # Extreme caution here. if ( $e =~ UNDEFINED_SUBROUTINE_ERROR ) { return FAIL; } elsif ( defined blessed $e ) { # Rethrow exception objects... die $e; } else { # Rethrow exception strings... if ( not $e = /\n\z/ ) { $e .= "\n"; } die $e; } } ... }
In reply to Trapping errors with specificity by diotalevi
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |