develooper Front page | perl.perl5.porters | Postings from May 2004

Re: [perl #29277] eof() on non-blocking filehandle

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
May 4, 2004 14:45
Subject:
Re: [perl #29277] eof() on non-blocking filehandle
Message ID:
20040504215002.GE1884@iabyn.com
On Fri, Apr 30, 2004 at 12:09:05PM -0000, perl-5. 8. 0 @ ton. iguana. be wrote:
> Using this testprogram:
> 
> #! /usr/bin/perl -wl
> use strict;
> use IO::Socket::INET;
> use POSIX qw(F_GETFL F_SETFL O_NONBLOCK);
> 
> pipe(my $rd, my $wr) || die "Could not create pipe: $!";
> my $flags = fcntl($rd, F_GETFL, 0) || die "Can't get fcntl flags: $!\n";
> fcntl($rd, F_SETFL, $flags | O_NONBLOCK) || die "Can't set fcntl flags: $!\n";
> select($wr);
> $|=1;
> close($wr) if @ARGV;
> my $rc = eof($rd);
> print STDERR defined($rc) ? $rc : "undef", "/$!";
> 
> Running it with an argument:
> 1/Illegal seek

The value of $! is irrelevant; it's only relevant on failed perl system
functions.

> Now without argument (not closing the write side of the pipe):
> 1/Illegal seek
> 
> mm, but there is no EOF this time....
> 
> Again looking at the strace:
> 
> pipe([3, 4])                            = 0
> ioctl(3, SNDCTL_TMR_TIMEBASE, 0xbfffeb40) = -1 EINVAL (Invalid argument)
> _llseek(3, 0, 0xbfffeb90, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
> ioctl(4, SNDCTL_TMR_TIMEBASE, 0xbfffeb40) = -1 EINVAL (Invalid argument)
> _llseek(4, 0, 0xbfffeb90, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
> fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
> fcntl64(4, F_SETFD, FD_CLOEXEC)         = 0
> fcntl64(3, F_GETFL)                     = 0 (flags O_RDONLY)
> fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
> read(3, 0x8175804, 4096)                = -1 EAGAIN (Resource temporarily unavailable)
> brk(0)                                  = 0x82bc800
> brk(0x82be000)                          = 0x82be000
> write(2, "1", 11)                        = 1
> write(2, "/Illegal seek", 13/Illegal seek)           = 13
> write(2, "\n", 1
> )                       = 1
> close(3)                                = 0
> close(4)                                = 0
> 
> So the read got EAGAIN (so perl should know it's not really EOF),
> but eof() still returns true, but i think it should have returned
> something false here. The errno is also strange (seemingly that old
> ESPIPE got saved and later restored, overwriting the EAGAIN).

Perl's eof is implemneted by going a getc and ungetc equivalent;
since these can change $!, but the Perl function eof() is documented
as not seeing $!, the old value has to be saved then restored.
Agin, the value of $! here is a bit of red herring.

The real issues, are whether eof() should be clever enough to understand
and handle non-blocking I/O (I presume that EAGAIN is system specific, at
least outside the UNIX world!), or whether this falls into the category
of mixing raw and buffered I/O, and thus get everything you deserve?

I guess NI-S might be able to comment better on this.

Dave.


-- 
"The GPL violates the U.S. Constitution, together with copyright,
antitrust and export control laws"
    -- SCO smoking crack again.

Thread Previous | 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