Skip Menu |

This queue is for tickets about the Lexical-Failure CPAN distribution.

Report information
The Basics
Id: 100284
Status: resolved
Priority: 0/
Queue: Lexical-Failure

People
Owner: Nobody in particular
Requestors: 'spro^^*%*^6ut# [...] &$%*c
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Bleadperl v5.21.3-644-ge52eb89 breaks Lexical::Failure
See <https://rt.perl.org/rt3/Ticket/Display.html?id=123172>. In short: $ perl5.8.9 -le 'sub { my $f; BEGIN { $ref = \$f; $f = 7; $$ref = 8; print $f } }' 8 $ perl5.10 -le 'sub { my $f; BEGIN { $ref = \$f; $f = 7; $$ref = 8; print $f } }' 7 $ perl5.20.1 -le 'sub { my $f; BEGIN { $ref = \$f; $f = 7; $$ref = 8; print $f } }' 7 $ perl5.21.5 -le 'sub { my $f; BEGIN { $ref = \$f; $f = 7; $$ref = 8; print $f } }' 8 You can see that \$stale_variable *copies* it, which results in buggy behaviour. You probably didn’t realise that your my $errmsg; use TestModule errors => \$errmsg; in t/inner_scalar.t was depending on this buggy behaviour. A reference to $errmsg was not being passed to TestModule::import, but, rather, a reference to a copy of $errmsg. As of 5.21.4, a reference to $errmsg is indeed passed to TestModule. Attached is an unfinished patch attempting to fix this another way. The only dependable way to see whether a variable is ‘unavailable’ is to look at the pad name. And to get to that, we need a sub ref and B.pm. I notice that t/inner_scalar.t has a comment saying: # Note: ideally the following would also warn when inner array used, but # there doesn't seem to be any way to actually detect the problem. :-( This fixes that, causing the test to fail, due to an incorrect test count (note the line 65). The line 81 mentioned in the test output is for my $outer_var; { subtest 'fail --> my outer scalar', sub { plan tests => 2; use TestModule errors => \$outer_var; ... which probably should *not* warn, right? I want your feedback before I finish this patch. Do you really want to depend on Devel::Caller as well? Do you think this B rummaging is worth it, or should the warning be skipped? If the warning should stay, do I need to comment the code copiously, so you can maintain it? :-) $ perl5.21.5 -Mblib t/inner_scalar.t 1..13 ok 1 - Warned as expected at line ok 2 - Warned as expected at line 26 ok 3 - Warning given ok 4 - Warned as expected at line ok 5 - Warned as expected at line 43 ok 6 - Warning given ok 7 - Warned as expected at line ok 8 - Warned as expected at line 65 ok 9 - Warned as expected at line 81 # Subtest: fail --> my inner scalar 1..2 ok 1 - Correct effects ok 2 - Failed to bind, as expected ok 10 - fail --> my inner scalar # Subtest: fail --> my inner hash 1..2 ok 1 - Correct effects ok 2 - Failed to bind, as expected ok 11 - fail --> my inner hash # Subtest: fail --> my inner array 1..2 ok 1 - Correct effects ok 2 - Failed to bind, as expected ok 12 - fail --> my inner array # Subtest: fail --> my outer scalar 1..2 ok 1 - Correct effects ok 2 - Successfully bound, as expected ok 13 - fail --> my outer scalar # Subtest: fail --> our package scalar 1..2 ok 1 - Correct effects ok 2 - Successfully bound, as expected ok 14 - fail --> our package scalar # Subtest: fail --> qualified package scalar 1..2 ok 1 - Correct effects ok 2 - Successfully bound, as expected ok 15 - fail --> qualified package scalar # Looks like you planned 13 tests but ran 15.
Subject: open_9sI9iRDm.txt
diff -rup Lexical-Failure-0.000006-G3OJHV/lib/Lexical/Failure.pm Lexical-Failure-0.000006-X3uPaH/lib/Lexical/Failure.pm --- Lexical-Failure-0.000006-G3OJHV/lib/Lexical/Failure.pm 2014-05-02 17:59:58.000000000 -0700 +++ Lexical-Failure-0.000006-X3uPaH/lib/Lexical/Failure.pm 2014-11-11 22:17:43.000000000 -0800 @@ -225,7 +225,29 @@ sub _check_scoping_of { my %vars = ( %{peek_our(3)}, %{peek_my(3)} ); # If it isn't any of them, warn us... - if (!grep { $vars{$_} == $target_var } keys %vars) { + my $found = grep { $vars{$_} == $target_var } keys %vars; + if ($found) { + # Unfind it if it closes over an anonymous sub's stale var. + use B; + use Devel::Caller 'caller_cv'; + my $cv = B::svref_2object(caller_cv(3)); + my $outer = $cv->OUTSIDE; + if (ref $outer ne 'B::SPECIAL' && $outer->CvFLAGS & B::CVf_ANON) { + my @pad = $cv->PADLIST->ARRAYelt($cv->DEPTH)->ARRAY; + for (0..$#pad) { + if (ref $pad[$_] ne 'B::SPECIAL' + && $pad[$_]->object_2svref == $target_var) + { + if ($cv->PADLIST->ARRAYelt(0)->ARRAYelt($_)->FLAGS + & B::SVf_FAKE) { + $found = 0; + last; + } + } + } + } + } + if (!$found) { return if _is_package_var($target_var); cluck 'Lexical ' . lc($var_type) . ' used as failure handler may not stay shared at runtime'; diff -rup Lexical-Failure-0.000006-G3OJHV/t/inner_scalar.t Lexical-Failure-0.000006-X3uPaH/t/inner_scalar.t --- Lexical-Failure-0.000006-G3OJHV/t/inner_scalar.t 2014-05-02 15:58:09.000000000 -0700 +++ Lexical-Failure-0.000006-X3uPaH/t/inner_scalar.t 2014-11-11 22:27:05.000000000 -0800 @@ -52,7 +52,7 @@ BEGIN { $SIG{__WARN__} = \&_check_warnin }; } -BEGIN { $SIG{__WARN__} = sub { _check_warning(@_) } } +#BEGIN { $SIG{__WARN__} = sub { _check_warning(@_) } } # Note: ideally the following would also warn when inner array used, but # there doesn't seem to be any way to actually detect the problem. :-(
Subject: Re: [rt.cpan.org #100284] Bleadperl v5.21.3-644-ge52eb89 breaks Lexical::Failure
Date: Thu, 13 Nov 2014 16:19:57 +1100
To: bug-Lexical-Failure [...] rt.cpan.org
From: Damian Conway <damian [...] conway.org>
Thank-you so much for this report, and for the terrifying patch, of which I am in awe! :-) I'm delighted that the original issue has led to a bug-fix in blead, and now that I better understand the matter, I've removed the funky "are we okay" testing within the module and thereby simplified and otherwise improved t/inner_scalar.t, so that it both tests more accurately and also passes consistently under 5.14 through 5.21. My goal was always just that any misuse of the "errors into variable" option (which I personally dislike, but which was widely requested) should be warned against, and I see now that that is achieved by Perl's built-in mechanisms (both before and after the bug-fix). As such, I've decided to remove the _check_scoping_of() call entirely. Hence, I won't need you to deep-comment your remarkable patch because I won't need to apply or maintain it....merely to marvel at it and then move quickly back into much shallower waters. ;-) Very much appreciated! Damian