X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FTry%2FTiny.pm;h=cf8f1f727898b2f39248419adfc4a6ba49e01301;hb=8447a3bf0e1b88bdd07fa584d83c81c64ad192cf;hp=7c97b62795a3af0f153869a5c326eb9a08ebf2f8;hpb=381a9eefb7552beca4573c574ce0732d5626bbbe;p=p5sagit%2FTry-Tiny.git diff --git a/lib/Try/Tiny.pm b/lib/Try/Tiny.pm index 7c97b62..cf8f1f7 100644 --- a/lib/Try/Tiny.pm +++ b/lib/Try/Tiny.pm @@ -29,6 +29,8 @@ BEGIN { *_HAS_SUBNAME = ($su || $sn) ? sub(){1} : sub(){0}; } +my @_finally_guards; + # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list # context & not a scalar one @@ -72,6 +74,15 @@ sub try (&;@) { _subname("${caller}::try {...} " => $try) if _HAS_SUBNAME; + # set up scope guards to invoke the finally blocks at the end. + # this should really be a function scope lexical variable instead of + # file scope + local but that causes issues with perls < 5.20 due to + # perl rt#119311 + local $_finally_guards[0] = [ + map { Try::Tiny::ScopeGuard->_new($_) } + @finally + ]; + # save the value of $@ so we can set $@ back to it in the beginning of the eval # and restore $@ after the eval finishes my $prev_error = $@; @@ -99,14 +110,12 @@ sub try (&;@) { $error = $@; $@ = $prev_error; - # set up a scope guard to invoke the finally block at the end - my @guards = - map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } - @finally; - # at this point $failed contains a true value if the eval died, even if some # destructor overwrote $@ as the eval was unwinding. if ( $failed ) { + # pass $error to the finally blocks + push @$_, $error for @{$_finally_guards[0]}; + # if we got an error, invoke the catch block. if ( $catch ) { # This works like given($error), but is backwards compatible and