develooper Front page | perl.perl5.porters | Postings from June 2012

Re: [perl #113764] [Regression] Re-opening scalar handles breaks on5.16.0

Thread Previous
From:
Jesse Luehrs
Date:
June 20, 2012 14:12
Subject:
Re: [perl #113764] [Regression] Re-opening scalar handles breaks on5.16.0
Message ID:
20120620211219.GM30375@tozt.net
On Wed, Jun 20, 2012 at 01:02:53PM -0700, Leon Timmermans wrote:
> The following piece of code works fine on 5.14 and 5.12 (and
> presumably on 5.8 and 5.10 too), but fails on 5.16. This breaks at
> least one of my CPAN modules:
> 
> open FILE, '>', \my $content or die "Couldn't open scalar filehandle";
> open my $fh, ">&=FILE" or die "Couldn't open: $!";
> print $fh "Foo-Bar\n";
> close $fh;
> close FILE;
> print $content;

49b69fb3a31122264bea3770d8f9d3e4a1a97186 is the first bad commit
commit 49b69fb3a31122264bea3770d8f9d3e4a1a97186
Author: Father Chrysostomos <sprout@cpan.org>
Date:   Mon May 7 20:43:18 2012 -0700

    [perl #112780] Don’t set cloned in-memory handles to ""
    
    PerlIO::scalar’s dup function (PerlIOScalar_dup) calls the base imple-
    mentation (PerlIOBase_dup), which pushes the scalar layer on to the
    new file handle.
    
    When the scalar layer is pushed, if the mode is ">" then
    PerlIOScalar_pushed sets the scalar to the empty string.  If it is
    already a string, it does this simply by setting SvCUR to 0, without
    touching the string buffer.
    
    The upshot of this is that newly-cloned in-memory handles turn into
    the empty string, as in this example:
    
    use threads;
    my $str = '';
    open my $fh, ">", \$str;
    $str = 'a';
    async {
        warn $str;  # something's wrong
    }->join;
    
    This has probably always been this way.
    
    The test suite for MSCHWERN/Test-Simple-1.005000_005.tar.gz does some-
    thing similar to this:
    
    use threads;
    my $str = '';
    open my $fh, ">", \$str;
    print $fh "a";
    async {
        print $fh "b";
        warn $str;  # "ab" expected, but 5.15.7-9 gives "\0b"
    }->join;
    
    What was happening before commit b6597275 was that two bugs were can-
    celling each other out: $str would be "" when the new thread started,
    but with a string buffer containing "a" beyond the end of the string
    and $fh remembering 1 as its position.  The bug fixed by b6597275 was
    that writing past the end of a string through a filehandle was leaving
    junk (whatever was in memory already) in the intervening space between
    the old end of string and the beginning of what was being written to
    the string.  This allowed "" to turn magically into "ab" when "b" was
    written one character past the end of the string.  Commit b6597275
    started zeroing out the intervening space in that case, causing the
    cloning bug to rear its head.
    
    This commit solves the problem by hiding the scalar temporarily
    in PerlIOScalar_dup so that PerlIOScalar_pushed won’t be able to
    modify it.
    
    Should PerlIOScalar_pushed stop clobbering the string and should
    PerlIOScalar_open do it instead?  Perhaps.  But that would be a bigger
    change, and we are supposed to be in code freeze right now.

:040000 040000 c6b08745fccce9963ab16647a41393f42e80484b 95e4780e1934da4e386690b2d18dee62515ca03b M      ext
bisect run success
That took 1485 seconds

-doy

Thread Previous


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