On Sat, 15 Jul 2017 12:07:19 -0700, c...@zoffix.com wrote:
> The original failure was in t/spec/S32-io/open.t test that I golfed
> down to the following:
> -----------------------8<---------------------------------
> $*IN = IO::Handle.new: :path('-'.IO);
> $*IN.open;
> $*OUT.open: :w;
> my $w = '-'.IO.open: :w;
> my $r = '-'.IO.open;
> $*IN.slurp(:close); #
> $w.put: 'meow  w';
> $*OUT.put: 'x';
> -----------------------8<---------------------------------
> Save that code to file named open.t and then run it like this:
> $ echo "x" | ./perl6 --ll-exception open.t
> And it'll die with 'Reading from filehandle failed: Bad file
> descriptor'
> This is on Rakudo version 2017.06-252-g83502cc built on MoarVM version
> 2017.06-91-g146c8fc.
> Most notably, removing `--ll-exception` parameter or even removing the
> `#` comment on line 6 causes the bug to disappear.

I investigated this a bit, wondering if the flakiness was a MoarVM bug. It 
turns out that no, MoarVM is doing precisely what is asked of it by Rakudo. :-)

The code in question makes the original handle bound in $*IN unreachable. At 
some point GC runs and collects it. Except it doesn't right away, because 
IO::Handle has a DESTROY method. That DESTROY method runs and closes the 
underlying VM handle. However, because the standard handles don't open a new 
handle, but rather obtain the VM-level handles for stdin/stderr/stdout, we can 
end up with two IO::Handle instances pointing to the same underlying handle. 
The DESTROY closes it, busting the other handle that holds it.

The various tweaks that hide the issue are simply moving when GC takes place, 
meaning it's too early or too late to collect the object and run DESTROY at the 
time that causes the breakage.


Reply via email to