On Mon Sep 09 12:28:08 2013, zefram@fysh.org wrote: > > This is a bug report for perl from zefram@fysh.org, > generated with the help of perlbug 1.39 running under perl 5.18.1. > > > ----------------------------------------------------------------- > [Please describe your issue here] > > Ran into this while tweaking Carp's localisation of $!: > > $ perl -le 'sub aa { local $!; ref($_[0]); 1 } $!=69; aa($!); print > 0+$!' > 0 > > $! is getting squashed to 0 despite "local $!". This only happens > if ref() gets applied to the $! argument, in its guise as $_[0]. > Doesn't happen with ref($!) or if the argument is something else. > If $! is set to a different value within the dynamic scope of "local > $!", that new value persists after the aa() call, regardless of > whether > the new value is assigned before or after the ref($_[0]). Also, if > "local $!" is removed then ref($_[0]) has no effect on $! (though $! > can > still be directly clobbered, of course). So evidentily the ref($_[0]) > is actually breaking the localisation per se. I think this is all stated elsewhere in the thread, but let me recap: Localisation swaps out a new $! and sets the old $! aside on the savestack, it invokes set-magic when localising (setting errno to 0) and when unwinding (setting it back to the value in the old $!). The old $! is still magical, so invoking get-magic on it will read errno into it, clobbering the only place where the old errno value is stored. I see multiple ways to fix this, each with its own drawbacks: 1) Make the old scalar temporarily non-magical when any magical scalar is localised. This would fix ticket #16235 ‘for free’. This could break modules like File::chdir that export a magical scalar to multiple callers. 2) Make the old scalar temporarily non-magical, but only if it is not tied. This would require using method #3 for tied variables; also, ticket #16235 would require a separate fix still, but only for ties. The result would be more complexity and some inconsistency between built-in variables like $! and tied variables. 3) Separately store the actual value to be restored on the savestack, in addition to the old magical scalar. #3 is the easiest to implement, and probably the safest in terms of backward compatibility. #2 might be the best fix overall though. It would make sub { local $!; print $_[0] }->($!) just DTRT without breaking ties. The inconsistency between ties and other magic may be acceptable. -- Father Chrysostomos --- via perlbug: queue: perl5 status: open https://rt.perl.org/Ticket/Display.html?id=119683Thread Next