Skip Menu |

This queue is for tickets about the Scalar-List-Utils CPAN distribution.

Report information
The Basics
Id: 65122
Status: rejected
Priority: 0/
Queue: Scalar-List-Utils

People
Owner: Nobody in particular
Requestors: LEONT [...] cpan.org
Cc:
AdminCc:

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



Subject: Correctly check PerlIO for open filehandle
Currently Scalar::Util's openhandle checks by checking for the definedness. This is not correct: fileno's documentation mentions «Filehandles connected to memory objects via new features of "open" may return undefined even though they are open.» This happens to work correctly on current versions of perl because of a bug that causes fileno to return -1 instead of undef on some occasions, but that will hopefully be fixed before the release of 5.14. This however will break the openhandle, so I've attached a patch that will check if a handle is open in the correct PerlIO way. Regards, Leon
Subject: openhandle.patch
diff --git a/lib/Scalar/Util.pm b/lib/Scalar/Util.pm index 24138ca..5086150 100644 --- a/lib/Scalar/Util.pm +++ b/lib/Scalar/Util.pm @@ -8,6 +8,7 @@ package Scalar::Util; use strict; use vars qw(@ISA @EXPORT_OK $VERSION @EXPORT_FAIL); +use Config; require Exporter; require List::Util; # List::Util loads the XS @@ -45,22 +46,33 @@ sub export_fail { @_; } +sub _is_openhandle; + +*_is_openhandle = ($] >= 5.008 and $Config{useperlio}) + ? sub { + my $fh = shift; + my $flags = (PerlIO::get_layers(*$fh, details => 1))[2]; + return defined $flags and $flags & 0x00200000; + } + : sub { + my $fh = shift; + return defined fileno $fh; + }; + sub openhandle ($) { my $fh = shift; my $rt = reftype($fh) || ''; - return defined(fileno($fh)) ? $fh : undef - if $rt eq 'IO'; + return _is_openhandle($fh) ? $fh : undef if $rt eq 'IO'; if (reftype(\$fh) eq 'GLOB') { # handle openhandle(*DATA) - $fh = \(my $tmp=$fh); + $fh = \(my $tmp=$fh); } elsif ($rt ne 'GLOB') { - return undef; + return undef; } - (tied(*$fh) or defined(fileno($fh))) - ? $fh : undef; + return (tied(*$fh) or _is_openhandle($fh)) ? $fh : undef; } 1; diff --git a/t/openhan.t b/t/openhan.t index bf4e6c1..8fab7d5 100644 --- a/t/openhan.t +++ b/t/openhan.t @@ -35,16 +35,15 @@ ok(defined &openhandle, 'defined'); SKIP: { skip "3-arg open only on 5.6 or later", 1 if $]<5.006; - open my $fh, "<", $0; - skip "could not open $0 for reading: $!", 1 unless $fh; + # Can't open $0 like that after a chdir + open my $fh, "<", $0 or skip "could not open $0 for reading: $!", 1; is(openhandle($fh), $fh, "works with indirect filehandles"); } SKIP: { skip "in-memory files only on 5.8 or later", 1 if $]<5.008; - open my $fh, "<", \"in-memory file"; - skip "could not open in-memory file: $!", 1 unless $fh; + open my $fh, "<", \"in-memory file" or skip "could not open in-memory file: $!", 1; is(openhandle($fh), $fh, "works with in-memory files"); } @@ -61,11 +60,11 @@ ok(openhandle(*DATA{IO}), "works for *DATA{IO}"); ok(!openhandle(IO::Handle->new), "unopened IO::Handle"); } -{ +SKIP: { require IO::File; my $fh = IO::File->new; $fh->open("< $0") - or skip "could not open $0: $!", 1; + or skip "could not open $0: $!", 2; ok(openhandle($fh), "works for IO::File objects"); ok(!openhandle(IO::File->new), "unopened IO::File" );