Opened 10 years ago

Last modified 9 years ago

#633 new defect

probe-file after delete-file succeeds

Reported by: metawilm Owned by: gb
Priority: normal Milestone:
Component: ANSI CL Compliance Version: trunk
Keywords: probe-file delete-file file Cc:

Description

Clozure Common Lisp Version 1.4-RC1-r13031 (WindowsX8632)

As I understand it, if delete-file returns T then the file is removed. So a subsequent probe-file should return nil to indicate the file is removed.

In the case below however, the probe-file after delete-file succeeds. I would expect either delete-file to fail, or probe-file to return nil.

? (progn (with-open-file (f "foo.lisp" :direction :output :if-exists :supersede)
           (format f "(in-package :cl-user)(format t \"hello\") (break \"break\")"))
         (let ((fasl-file (compile-file "foo.lisp")))
           (format t "fasl-file: ~A~%" fasl-file)
           (restart-bind ((delete-fasl
                              (lambda (&optional c)
                                (declare (ignore c))
                                (format t "delete-file: ~A~%" (delete-file fasl-file))
                                (format t "probe-file: ~A~%" (probe-file fasl-file)))
                              :report-function
                                (lambda (s) (format s "My restart..."))))
             (load fasl-file))))
fasl-file: C:/Willem/lisp/cl-python/foo.wx32fsl
hello
> Break: break
> While executing: #<Anonymous Function #x93E4DB6>, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Return from BREAK.
> Type :? for other options.
1 > :r
>   Type (:C <n>) to invoke one of the following restarts:
0. Return to break level 1.
1. #<RESTART ABORT-BREAK #x116F7E6>
2. Return from BREAK.
3. Load "foo.lisp" instead of "C:/Willem/lisp/cl-python/foo.wx32fsl"
4. Compile "foo.lisp" into "C:/Willem/lisp/cl-python/foo.wx32fsl" then load "C:/Willem/lisp/cl-python/foo.wx32fsl" again
5. Retry loading #P"C:/Willem/lisp/cl-python/foo.wx32fsl"
6. Skip loading #P"C:/Willem/lisp/cl-python/foo.wx32fsl"
7. Load other file instead of #P"C:/Willem/lisp/cl-python/foo.wx32fsl"
8. My restart...
9. Return to toplevel.
10. #<RESTART ABORT-BREAK #x116FCA6>
11. Reset this thread
12. Kill this thread
1 > :c 8
Invoking restart: My restart...
delete-file: T
probe-file: C:/Willem/lisp/cl-python/foo.wx32fsl
1 > 

Change History (3)

comment:1 Changed 10 years ago by rme

http://bugs.python.org/issue7443 seems to describe a similar issue.

comment:2 Changed 10 years ago by gb

Windows doesn't delete files that're still open; that would make too much sense, so it simply turns them into zombies (that can only die when they're closed). Subsequent attempts to create a file with the same name as one of the Undead will fail, as will attempts to open the existing file again.

AFAIK, the Windows primitive that's used to implement DELETE-FILE returns the same success indicator regardless of whether the file is actually deleted or merely scheduled for deletion, and I don't know of any way for PROBE-FILE to determine whether a file really exists or is in this zombie-like state.

If I understand and remember this correctly, I don't think that there's any way that we can fix this; the only way that I know of to (at all) reliably detect the case where a file's in this zombie-like state is to try to open it and check the error, and that's not a reasonable thing for either DELETE-FILE or PROBE-FILE to do.

comment:3 Changed 9 years ago by rme

There may be non-straightforward ways. We could, for instance, try to move the file to the recycle bin in a case like this. However, handling all the cases seems to get really complicated, Cygwin goes through all sorts of horrible gyrations:

http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/syscalls.cc?cvsroot=src

These may all fall into the category of things that are not reasonable for delete-file or probe-file to do.

FWIW, on another implementation (LispWorks), the delete-file fails with an error ("The process cannot access the file because it is being used by another process")

Note: See TracTickets for help on using tickets.