Subject: Re: Testing for the EOF on byte streams
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 08 Feb 2008 22:42:57 -0600
Newsgroups: comp.lang.lisp
Message-ID: <GY6dnTI8v_bMsjDanZ2dnUVZ_uSgnZ2d@speakeasy.net>
Marco Antoniotti  <marcoxa@gmail.com> wrote:
+---------------
| p...@informatimago.com (Pascal J. Bourguignon) | wrote:
| > feof(3) just returns a flag that is set by the stdio routines that
| > call read(2) and get a eof-value.
| >
| > There is no eof(2) syscall!
| >
| > Note how the POSIX specification for feof avoid mentioning anything
| > about the actual "end of the file", but refers only the end-of-file
| > indicator of the stream. �This indicator is set to true when read(2)
| > returned the eof value ...
| 
| Yes.  And you simulated this effect in your other post with the FILE
| struct.
| 
| Reading the POSIX and ISO-C specs made me think that feof() is used
| only ex-post alongside ferror() to see what happened when a read
| operation went awry.  So, probably I will have to change my logic
| after all.
+---------------

(*sigh*) Yes, probably. You wouldn't if LISTEN worked "properly",
but it doesn't [can't?], at least not on Unix/Linux systems.

    Function LISTEN
    ...
    If an end of file is encountered, listen returns NIL..

This has two problems:

1. LISTEN should really be defined as being READ-WOULD-NOT-HANG (IMHO),
   and if defined that way then on EOF it would return T, not NIL,
   the way BSD "listen()" does.[1] And a subsequent READ *wouldn't*
   hang, but get an instant EOF.

2. The CLHS quote above speaks of the end of file being "encountered",
   without answering "encountered by whom?", which implies that a call
   to LISTEN might not be enough to "encounter" the EOF, leaving the
   implementation free to do weird things like this, where "tmp2" is
   a file with three lines in it:

      > (with-open-file (s "tmp2")
	  (list (read-line s nil 'my-eof)
	        (read-line s nil 'my-eof)
	        (read-line s nil 'my-eof)
	        (listen s)
	        (read-line s nil 'my-eof)
	        (listen s)))

      ("foo" "bar" "baz" T MY-EOF NIL)
      > 

   It's not until the EOF was "encountered" by the 4th READ-LINE
   that LISTEN was informed of the EOF (via internal side-channel).
   And, of course, as Pascal suggests, that's probably because
   there's no "eof(2)" syscall on this system, a Unix/Linux.

Oh, well...


-Rob

[1] BSD-style "select()" at least *does* give you a "readable"
    indication on a socket EOF, which means that if you "select()"
    before every "read()" you can almost get what you want.
    Trouble is, you can't use this approach everywhere, since
    there are some Linux "/proc" files that *never* return
    "readable" indications from "select()", even when a "read()"
    would *not* block! But that's a battle for another day...

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607