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

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

Thread Previous
May 5, 2004 06:22
Re: [perl #29277] eof() on non-blocking filehandle
Message ID:
In article <>,
	Dave Mitchell <> writes:
> 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.
Well, not completely. Indeed $! only gets a guaranteed value after 
a failing systemcall, and stdio functions aren't even systemcalls. 
However, the way it normally works is that perl doesn't play with $! 
(or errno at the C level really), and just lets libc do its job. 
In particular if I use perl operators corresponding to stdio functions, 
I usually expect $! to show what the corresponding stdio function 
would return. 

But yeah, that's just an expectation, not guaranteed in the perl docs, 
so I wasn't calling the $! behaviour a bug. But still, I find the 
save/restore behaviour that eof() does on $! unexpected and it also 
seems pointless (my version of the eof() docs (perl 5.8.2) at least 
don't say that $! gets saved and restored).

> 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?

Using stdio functions on non-blocking sockets is not what I personally
would do, but it's a valid programming style nevertheless.
However it works at the systemcall level not visible for the perl user,
I think eof() should return some false value for the case of a non-closed
non-blocking socket (undef would be my personal preference), and while
$! probably won't be documented as anything particular, naively I would 
expect to see EAGAIN. And by not trying to be clever about $! save/restore, 
I think that would actually happen automatically.

Trying to formulate what I'd want to happen purely in terms of 
getc/ungetc, I also notice that if in my test program I replace 
eof($rd) with getc($rd), I see:

undef/Bad file descriptor

in both cases (closed or non-closed non-blocking socket). The getc() docs
DO talk about $!, but only say that in the error case it will have a value.
It implies (but indeed doesn't say) that for the eof case, $! should be
empty, otherwise you cannot distinguish the two cases (error versus eof).

And "Bad file descriptor" is even a very unexpected error for the 
non-closed case (where supposedly the docs say I should get a valid $!). 
It's not the correct errno nor does an strace show any EBADF happening on 
any of the system calls.

Thread Previous Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About