develooper Front page | perl.perl5.porters | Postings from October 2013

[perl #119683] $! localisation broken by ref

Thread Next
From:
Father Chrysostomos via RT
Date:
October 26, 2013 08:17
Subject:
[perl #119683] $! localisation broken by ref
Message ID:
rt-4.0.18-14233-1382775414-586.119683-15-0@perl.org
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=119683

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About