From: Sam S. <sd...@gn...> - 2018-11-12 18:19:52
|
On Sun, Nov 11, 2018 at 6:50 PM Bruno Haible <br...@cl...> wrote: > Sam asked: > > I discovered > > that `with-open-file' is implemented differently in CLISP and SBCL: > > > > (LET ((A (OPEN "f"))) > > (DECLARE (SYSTEM::READ-ONLY A)) > > (UNWIND-PROTECT (MULTIPLE-VALUE-PROG1 (PROGN (PRINT 1 A)) (WHEN A (CLOSE A))) > > (WHEN A (CLOSE A :ABORT T)))) > > > > vs > > > > (LET ((A (OPEN "f")) (#:G368 T)) > > (UNWIND-PROTECT (MULTIPLE-VALUE-PROG1 (PROGN (PRINT 1 A)) (SETQ #:G368 NIL)) > > (WHEN A (CLOSE A :ABORT #:G368)))) > > > > The second version produces a marginally smaller bytecode (probably > > unimportant) and seems slightly more aesthetic (calls CLOSE only once). > > > > Why did you choose the first version? > > I did so for reliability. When the disk gets full, this produces an error > condition. Most often, the error condition will occur during the body that > produces output. But recall that a file-stream is most often buffered, and > that means that some output is still waiting in the buffer until the final > (CLOSE A) call; if the disk full error only occurs in this last file system > access, > * the clisp variant will execute the protection clause (CLOSE A :ABORT T) > and thus do as specified in ANSI CL [1]: "the file system is left, so far > as possible, as if the file had never been opened." > * the sbcl variant will not execute (CLOSE A :ABORT T) and thus leave a > file on the (full) disk that is truncated. > > WITH-OPEN-FILE was designed to avoid leaving truncated files on disk, and > an implementation should better achieve this goal in 100%, not 99%, of the > cases. > [1] http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_with-open-file.html Ah, now I remember asking this question 10 or 20 years ago ;-) However, looking at stream.d:low_close_handle, it does not look like your impeccable theoretical justification has a practical underpinning. IOW, if ENOSP is raised in (CLOSE A), the subsequent (CLOSE A :ABORT T) does not seem to be removing the file. (note that, in fact, removing the file is not necessarily TRT if the file existed before OPEN or if FINISH-OUTPUT has been called). If your point it that the "recovery" should be done at the OS level, then it does not look like any existing OS distinguishes between ABORT and non-ABORT close(), so the issue is actually moot. Another weirdness is that `with-open-file` is defined separately instead of via `with-open-stream`... -- Sam Steingold <http://sds.podval.org> <http://www.childpsy.net> <http://steingoldpsychology.com> |