Improve handling of Perl's block eval errors #768
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Taken from
Perl::Critic
:A common idiom in perl for dealing with possible errors is to use
eval
followed by a check of
$@
/$EVAL_ERROR
:There's a problem with this: the value of
$EVAL_ERROR
($@
) can changebetween the end of the
eval
and theif
statement. The issue are objectdestructors:
Assuming there are no other references to
$foo
created, when theeval
block inmain
is exited,Foo::DESTROY()
will be invoked,regardless of whether the
eval
finished normally or not. If theeval
in
main
fails, but theeval
inFoo::DESTROY()
succeeds, then$EVAL_ERROR
will be empty by the time that theif
is executed.Additional issues arise if you depend upon the exact contents of
$EVAL_ERROR
and botheval
s fail, because the messages from both willbe concatenated.
Even if there isn't an
eval
directly in theDESTROY()
method code,it may invoke code that does use
eval
or otherwise affects$EVAL_ERROR
.The solution is to ensure that, upon normal exit, an
eval
returns atrue value and to test that value:
Unfortunately, you can't use the
defined
function to test the result;eval
returns an empty string on failure.Various modules have been written to take some of the pain out of
properly localizing and checking
$@
/$EVAL_ERROR
. For example:"But we don't use DESTROY() anywhere in our code!" you say. That may be
the case, but do any of the third-party modules you use have them? What
about any you may use in the future or updated versions of the ones you
already use?