From: Haiwei
Subject: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <24e667c1-b3ef-4e64-adc6-15b477bff12a@z26g2000pre.googlegroups.com>
Hi,

When executing following expression, the output file only has part of
contents. The size of this file is 12281.

(let ((*standard-output* (open "/home/haiwei/tmp/tmplog"
                               :if-exists :rename-and-delete
                               :if-does-not-exist :create
                               :direction :output)))
  (judydl-enumerate root je))

But I wrote another function which open a file and write data into
it.  Then I got all the contents.
Is there any buffer or size limit on *standard-output* in sbcl?
My OS is ubuntu 8.04. The version of sbcl is 1.0.11.debian.

(defun judydl-enumerate-file (root je file)
  (with-open-stream (stream (open file :if-exists :rename-and-
delete :if-does-not-exist :create :direction :output))
    (let ((len 0)
          (value 0)
          (index (make-string 100))
          (outlen (make-alien (unsigned))))
      (setf (deref outlen) 100)
      (loop for p = (JudyDLFirst (deref root)
                                 (sap-alien (sb-sys:vector-sap index)
                                            (* char))
                                 len
                                 outlen
                                 je)
              then (JudyDLNext (deref root)
                               (sap-alien (sb-sys:vector-sap index)
                                          (* char))
                               len
                               outlen
                               je)
            while (not (eq (sb-sys:sap-int (alien-sap p)) 0)) ;fixme
            do (progn
                 (setf len (deref outlen))
                 (setf value (deref (cast p (* (unsigned)))))
                 (when (> value 10)
                   (format stream "~A ~A~%" (subseq index 0 (/ len 4))
value)))))))

Thanks,
Haiwei

From: Pascal J. Bourguignon
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <7cd4kvy0d0.fsf@pbourguignon.anevia.com>
Haiwei <·········@gmail.com> writes:

> Hi,
>
> When executing following expression, the output file only has part of
> contents. The size of this file is 12281.
>
> (let ((*standard-output* (open "/home/haiwei/tmp/tmplog"
>                                :if-exists :rename-and-delete
>                                :if-does-not-exist :create
>                                :direction :output)))
>   (judydl-enumerate root je))

You don't close the file, so some bytes remain in the buffer.


> But I wrote another function which open a file and write data into
> it.  Then I got all the contents.
> Is there any buffer or size limit on *standard-output* in sbcl?
> My OS is ubuntu 8.04. The version of sbcl is 1.0.11.debian.

No, just be sure to close the file.  WITH-OPEN-STREAM makes sure 
stream is closed, which is why JUDYDL-ENUMERATE-FILE works.
By the way, isn't there anything choking you?

        WITH-OPEN-STREAM 
 JUDYDL-ENUMERATE-FILE

Use rather WITH-OPEN-FILE, in JUDYDL-ENUMERATE-FILE.  
Or implement a JUDYDL-ENUMERATE-STREAM.


In general, you will use WITH-OPEN-FILE.  

-- 
__Pascal Bourguignon__
From: Haiwei
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <c76db854-1383-4ab6-8b27-0ee98c16e1e8@a8g2000prf.googlegroups.com>
On Jul 30, 9:20 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Haiwei <·········@gmail.com> writes:
> > Hi,
>
> > When executing following expression, the output file only has part of
> > contents. The size of this file is 12281.
>
> > (let ((*standard-output* (open "/home/haiwei/tmp/tmplog"
> >                                :if-exists :rename-and-delete
> >                                :if-does-not-exist :create
> >                                :direction :output)))
> >   (judydl-enumerate root je))
>
> You don't close the file, so some bytes remain in the buffer.

Thanks. I got all the output after closed the stream.

>
> > But I wrote another function which open a file and write data into
> > it.  Then I got all the contents.
> > Is there any buffer or size limit on *standard-output* in sbcl?
> > My OS is ubuntu 8.04. The version of sbcl is 1.0.11.debian.
>
> No, just be sure to close the file.  WITH-OPEN-STREAM makes sure
> stream is closed, which is why JUDYDL-ENUMERATE-FILE works.
> By the way, isn't there anything choking you?
>
>         WITH-OPEN-STREAM
>  JUDYDL-ENUMERATE-FILE
>
> Use rather WITH-OPEN-FILE, in JUDYDL-ENUMERATE-FILE.  
> Or implement a JUDYDL-ENUMERATE-STREAM.
>
> In general, you will use WITH-OPEN-FILE.  

Yes. I will. But when to use WITH-OPEN-STREAM?

>
> --
> __Pascal Bourguignon__
From: Joshua Taylor
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <d5888b2c-bfc5-4826-8405-1bce7b7ff227@k13g2000hse.googlegroups.com>
On Jul 30, 9:38 am, Haiwei <·········@gmail.com> wrote:
> On Jul 30, 9:20 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
> > Haiwei <·········@gmail.com> writes:
> > > Hi,
>
> > > When executing following expression, the output file only has part of
> > > contents. The size of this file is 12281.
>
> > > (let ((*standard-output* (open "/home/haiwei/tmp/tmplog"
> > >                                :if-exists :rename-and-delete
> > >                                :if-does-not-exist :create
> > >                                :direction :output)))
> > >   (judydl-enumerate root je))
>
> > You don't close the file, so some bytes remain in the buffer.
>
> Thanks. I got all the output after closed the stream.
>
> > > But I wrote another function which open a file and write data into
> > > it.  Then I got all the contents.
> > > Is there any buffer or size limit on *standard-output* in sbcl?
> > > My OS is ubuntu 8.04. The version of sbcl is 1.0.11.debian.
>
> > No, just be sure to close the file.  WITH-OPEN-STREAM makes sure
> > stream is closed, which is why JUDYDL-ENUMERATE-FILE works.
> > By the way, isn't there anything choking you?
>
> >         WITH-OPEN-STREAM
> >  JUDYDL-ENUMERATE-FILE
>
> > Use rather WITH-OPEN-FILE, in JUDYDL-ENUMERATE-FILE.  
> > Or implement a JUDYDL-ENUMERATE-STREAM.
>
> > In general, you will use WITH-OPEN-FILE.  
>
> Yes. I will. But when to use WITH-OPEN-STREAM?
>

The Hyperspec says about WITH-OPEN-FILE, "with-open-file uses open to
create a file stream to file named by filespec. Filespec is the name
of the file to be opened. Options are used as keyword arguments to
open." From an issue write (about dynamic extent, not directly
relevant here), "[WITH-OPEN-FILE] probably should inherit whatever
restrictions are placed on WITH-OPEN-STREAM, so you can implement it
that way."

This suggests that WITH-OPEN-FILE could be implemented as

(defmacro with-open-file2 ((var filename &rest options) &body body)
  `(with-open-stream (,var (open ,filename ,@options))
     ,@body))

So I'd guess that WITH-OPEN-STREAM is the choice whenever the stream
isn't going to be associated with a file. There are a number of other
stream constructors other than open, including MAKE-SYNONYM-STREAM,
MAKE-BROADCAST-STREAM, MAKE-TWO-WAY-STREAM, MAKE-ECHO-STREAM... (I'm
getting these from http://www.lisp.org/HyperSpec/Body/sec_the_streams_dictionary.html
.)

//JT

>
>
> > --
> > __Pascal Bourguignon__
From: Richard M Kreuter
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <87od4ffezy.fsf@progn.net>
Joshua Taylor <···········@gmail.com> writes:

> The Hyperspec says about WITH-OPEN-FILE, "with-open-file uses open
> to create a file stream to file named by filespec. Filespec is the
> name of the file to be opened. Options are used as keyword arguments
> to open." From an issue write (about dynamic extent, not directly
> relevant here), "[WITH-OPEN-FILE] probably should inherit whatever
> restrictions are placed on WITH-OPEN-STREAM, so you can implement it
> that way."
>
> This suggests that WITH-OPEN-FILE could be implemented as
>
> (defmacro with-open-file2 ((var filename &rest options) &body body)
>   `(with-open-stream (,var (open ,filename ,@options))
>      ,@body))

Not necessarily.  WITH-OPEN-FILE has an extra requirement:

|  If a new output file is being written, and control leaves
|  abnormally, the file is aborted and the file system is left, so far
|  as possible, as if the file had never been opened.

I don't see anything in WITH-OPEN-STREAM to suggest that it's supposed
to do anything interesting in case of abnormal transfer out of the
body.

--
RmK
From: Joshua Taylor
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <0a9b6a13-0295-411a-a898-1674e0f3127d@26g2000hsk.googlegroups.com>
On Jul 30, 1:39 pm, Richard M Kreuter <·······@progn.net> wrote:
> Joshua Taylor <···········@gmail.com> writes:
> > The Hyperspec says about WITH-OPEN-FILE, "with-open-file uses open
> > to create a file stream to file named by filespec. Filespec is the
> > name of the file to be opened. Options are used as keyword arguments
> > to open." From an issue write (about dynamic extent, not directly
> > relevant here), "[WITH-OPEN-FILE] probably should inherit whatever
> > restrictions are placed on WITH-OPEN-STREAM, so you can implement it
> > that way."
>
> > This suggests that WITH-OPEN-FILE could be implemented as
>
> > (defmacro with-open-file2 ((var filename &rest options) &body body)
> >   `(with-open-stream (,var (open ,filename ,@options))
> >      ,@body))
>
> Not necessarily.  WITH-OPEN-FILE has an extra requirement:
>
> |  If a new output file is being written, and control leaves
> |  abnormally, the file is aborted and the file system is left, so far
> |  as possible, as if the file had never been opened.
>
> I don't see anything in WITH-OPEN-STREAM to suggest that it's supposed
> to do anything interesting in case of abnormal transfer out of the
> body.

Ah, good catch. So we have at least two cases for WITH-OPEN-STREAM,
one of which is when the stream isn't one easily produced by OPEN, and
another which is when the stream can be created by OPEN, but if
something happens in the middle, the file should still be present
afterward. Have we got any more cases?

//JT
From: Nikodemus Siivola
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <7634543c-4b80-4caf-9b8d-3f502484641c@m36g2000hse.googlegroups.com>
On Jul 30, 5:34 pm, Joshua Taylor <···········@gmail.com> wrote:

> This suggests that WITH-OPEN-FILE could be implemented as
>
> (defmacro with-open-file2 ((var filename &rest options) &body body)
>   `(with-open-stream (,var (open ,filename ,@options))
>      ,@body))

This is not interrupt safe: if an asynch unwind occurs after open, but
before the UNWIND-PROTECT from W-O-S has been entered, the file will
be left open. (Ok, there is no guarantee that WITH-OPEN-FILE is async
signal safe -- or indeed anything, but you can always hope.)

Cheers,

 -- Nikodemus
From: Richard M Kreuter
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <87k5f2f9ak.fsf@progn.net>
Nikodemus Siivola <·········@random-state.net> writes:

> On Jul 30, 5:34 pm, Joshua Taylor <···········@gmail.com> wrote:
>
>> This suggests that WITH-OPEN-FILE could be implemented as
>>
>> (defmacro with-open-file2 ((var filename &rest options) &body body)
>>   `(with-open-stream (,var (open ,filename ,@options))
>>      ,@body))
>
> This is not interrupt safe: if an asynch unwind occurs after open, but
> before the UNWIND-PROTECT from W-O-S has been entered, the file will
> be left open. (Ok, there is no guarantee that WITH-OPEN-FILE is async
> signal safe -- or indeed anything, but you can always hope.)

Who says WITH-OPEN-STREAM isn't defined as if by

(defmacro with-open-stream ((var form) &body body)
  `(ext:without-interrupts
    (let ((,var ,form))
      (unwind-protect
          (ext:allow-interrupts (progn ,@body))
        (close ,var)))))

?  (For suitable WITHOUT-INTERRUPTS and ALLOW-INTERRUPTS, of course.)

--
RmK
From: Thomas A. Russ
Subject: Re: Strange behaviour of *standard-output* in sbcl
Date: 
Message-ID: <ymik5f3ciwc.fsf@blackcat.isi.edu>
···@informatimago.com (Pascal J. Bourguignon) writes:

> Haiwei <·········@gmail.com> writes:
> 
> > Hi,
> >
> > When executing following expression, the output file only has part of
> > contents. The size of this file is 12281.
> >
> > (let ((*standard-output* (open "/home/haiwei/tmp/tmplog"
> >                                :if-exists :rename-and-delete
> >                                :if-does-not-exist :create
> >                                :direction :output)))
> >   (judydl-enumerate root je))
> 
> You don't close the file, so some bytes remain in the buffer.
...

Also, it is often useful to include FORCE-OUTPUT at places where
interactive streams, in particular, are used.


> Use rather WITH-OPEN-FILE,...

And to amplify Pascal's advice, I will point out that you can use
WITH-OPEN-FILE to bind *standard-output* as well:

(with-open-file (*standard-output* "/home/haiwei/tmp/tmplog"
                                   :if-exists :rename-and-delete
                                   :if-does-not-exist :create
                                   :direction :output)
   (judydl-enumerate root je))


-- 
Thomas A. Russ,  USC/Information Sciences Institute