sub foo { local $@; eval { # a generic wrapper, doesn'tknow about bar()'s details bar(); }; if ( $@ ) { # do something meaningful die $@; } } sub bar { die "blah"; } eval { foo() }; warn "Error: $@"; in the 'foo' subroutine $@ is localized to prevent clobbering it in cases such as: eval { ... }; foo(); if ( $@ ) { # for the prev eval } From a control flow POV everything works correctly here, but in the outermost eval { } the value of $@ is not preserved (it will jump though). The value is just ''. Since there is no other way to know if the eval actually failed without inspecting $@ that makes it faily useless, and furthermore the documentation of eval implies this should not be the case (but doesn't mention local). I believe this is an implementation detail, likely die() in the context of an eval assigning to $@ with it's localization stack, instead of the assignment happenning in the scope of the eval { } that is actually trapping the error, so in effect the error that it trapped is in $@. The work around is in foo(): sub foo { my $e; { local $@; eval { bar () }; $e = $@; } if ( $e ) { die $e } } but that kinda sucks. Every time this happenned to me it took a really long while to figure out, a conservative guess is that I've lost about 2-3 days of my life to this behavior over the past few years. This is because it's action at a distance on several levels. -- Yuval Kogman <nothingmuch@woobling.org> http://nothingmuch.woobling.org 0xEBD27418Thread Next