Re: Odd behavior for manually-constructed file-stream

Gary Byers <[email protected]> Mon, 25 Sep 2006 10:11:23 -0600 (MDT)
Newsgroups gmane.lisp.openmcl.bugs
Message-ID <[email protected]>

On Sun, 24 Sep 2006, Richard M Kreuter wrote:

> Hello,
>
> Using OpenMCL 1.0 PPC/Linux, I'm having trouble figuring out how to
> acheive consistency across print/file-position/read operations on a
> file-stream made with ccl::make-fd-stream.
>
> The strangeness is this: a print followed by a file-position followed
> by a read signals an end-of-file error unless both (1) force-output is
> called between the print and the file-position and (2) the postition
> argument to file-position was greater than 1.
>
> By inspection, neither of these is required for streams with direction
> :io created by open, so I'm confused about what the intended behavior
> is supposed to be on OpenMCL.

File streams created with OPEN call FORCE-OUTPUT and otherwise do the
right thing(s) with buffering when FILE-POSITION is called on them.

In general, streams created with CCL::MAKE-FD-STREAM don't.  (It's
intended for non-seekable things like pipes and sockets and ptys.)

>
> Below are some transcripts that demonstrate the behaviors described
> above.
>
> What am I doing wrong?

Why are you using CCL::MAKE-FD-STREAM ?

(If the answer is "because you already had a file descriptor and
wanted to use stream functions to access it, as in your example"
... it'd be handy to have something like that - something like OPEN
that took an open FD rather than a pathname - but it doesn't really
exist.)

One very, very sleazy way of doing that - that might almost work -
would be to use OPEN to create a file stream to some (other) temporary
file, then use the #_dup2 functon to make the file descriptor of that
stream match the file descriptor in question.  Something like:

(defun get-file-stream-for-fd (fd &rest open-args)
   (let* ((stream (apply #'open "/some/random/file" open-args)))
     ;; Some stream classes use different file descriptors
     ;; for input and output.  FILE-STREAMs opened for I/O use the same
     ;; descriptor in both directions, but CCL::STREAM-DEVICE wants
     ;; its second arg to be one of :INPUT or :OUTPUT (and the stream
     ;; has to be open in the direction indicated by that arg.)
     (#_dup2 fd (ccl::stream-device stream :input))
     stream))

That's untested (and admittedly very, very sleazy.)


>
> Thanks in advance,
> RmK
> --
>
> ;; Behavior of a stream constructed by OPEN.  No force-outputs are
> ;; necessary, and setting file-position to 0 works as I'd expect.
> ;; Not using with-open-file just for symmetry with the following
> ;; examples.
> CL-USER> (with-open-stream (stream
> 			    (open "/tmp/foo.tmp"
> 				  :direction :io :if-exists :supersede))
> 	   (print 'bar stream)
> 	   (file-position stream 0)
> 	   (read-char stream))
> #\Newline
> CL-USER> (with-open-stream (stream
> 			    (open "/tmp/foo.tmp"
> 				  :direction :io :if-exists :supersede))
> 	   (print 'foo stream)
> 	   (file-position stream 0)
> 	   (read stream))
> FOO
>
> ;; Use cffi to define tmpfile() and fileno() functions.
> CL-USER> (defpackage tmpfile (:use :cl :cffi))
> #<Package "TMPFILE">
> CL-USER> (in-package tmpfile)
> #<Package "TMPFILE">
> TMPFILE> (defcfun "tmpfile" :pointer)
> TMPFILE
> TMPFILE> (defcfun "fileno" :int (file :pointer))
> FILENO
> TMPFILE> (defun make-tmpfile ()
> 	   (let ((file (tmpfile)))
> 	     (let ((fd (unwind-protect
> 			    (fileno file)
> 			 (foreign-free file))))
> 	       (ccl::make-fd-stream fd :direction :io
>                                       :class 'file-stream))))
> MAKE-TMPFILE
>
> ;; Verify that make-tmpfile does something.
> TMPFILE> (make-tmpfile)
> #<FILE-CHARACTER-IO-STREAM (NIL/9) #x35516FE6>
> TMPFILE> (close *)
> T
>
> ;; Try the same routine as above:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> 	   (print 'bar stream)
> 	   (file-position stream 0)
> 	   (read-char stream))
> Unexpected end of file on #<FILE-CHARACTER-IO-STREAM (NIL/9) #x355101DE>
>   [Condition of type END-OF-FILE]
> ; Evaluation aborted
>
> ;; Try force-output:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> 	   (print 'bar stream)
> 	   (force-output stream)
> 	   (file-position stream 0)
> 	   (read-char stream))
> Unexpected end of file on #<FILE-CHARACTER-IO-STREAM (NIL/9) #x3556A216>
>   [Condition of type END-OF-FILE]
> ; Evaluation aborted
>
> ;; Try setting the file-position to 1 instead of 0:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> 	   (print 'bar stream)
> 	   (file-position stream 1)
> 	   (read-char stream))
> Unexpected end of file on #<FILE-CHARACTER-IO-STREAM (NIL/9) #x3559DA0E>
>   [Condition of type END-OF-FILE]
> ; Evaluation aborted
>
> ;; Using both force-output and setting the file-position to 1:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> 	   (print 'bar stream)
> 	   (force-output stream)
> 	   (file-position stream 1)
> 	   (read-char stream))
> #\B
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> 	   (print 'foo stream)
> 	   (force-output stream)
> 	   (file-position stream 1)
> 	   (read stream))
> FOO
>
> _______________________________________________
> Bug-openmcl mailing list
> [email protected]
> http://clozure.com/mailman/listinfo/bug-openmcl
>
>