Home | Libraries | People | FAQ | More |
On POSIX you are allowed to call unlink()
on a file which is open for use —
indeed this is a very convenient way of creating an anonymous private temporary
file whose storage will be deallocated on the last file handle close. Ordinarily
Windows does not permit deletion or renaming of files still in use, but if
all open handles to that file were opened with FILE_SHARE_DELETE
then it can permit renames and deletions of open files.
There are however some gotchas with this, and it is worth listing them here. Firstly, Windows never allows you to really delete an open file, rather it is flagged as delete pending and its entry in its directory remains visible (though no new file handles may be opened to it) and when the very last open handle to the file in the system is closed, only then is it truly deleted. Well, actually only sort of truly deleted, because Windows only appears to remove the file entry from the directory, but in fact that entry is merely hidden and actually still exists and attempting to create a file with the same name will return an access denied error. How long it silently exists for depends on a range of factors, but put it this way: if your code loops creating and deleting the same file name as you might when operating a lock file, you're going to see lots of random spurious access denied errors and truly dismal lock file performance compared to POSIX.
Note that this lazy file deletion is different from “file tunnelling” whereby a file created with the same name as a recently deleted file silently inherits its creation time and other metadata. I mention this because this feature also gets in the way of POSIX file semantics, but for other reasons.
AFIO works around these un-POSIX file semantics by taking a dual step to
deleting files. Firstly, it renames the file to a 128 bit cryptographically
strong random name prefixed by “.afiod” into as high up the
directory hierarchy as it is able to, and only then does it request the deletion
of the file. As AFIO always opens files with FILE_SHARE_DELETE
permission enabled, with that flag Windows permits renaming and deletion,
and because the name was changed to a very random name somewhere not in its
origin directory before deletion, you don't see those unexpected and random
errors when creating files with the same name as a recently deleted file
as you do anywhere else on Windows. Because the file is probably not in its
original containing directory any more, deletions of that directory will
not fail with “directory not empty” as they otherwise normally
would and indeed do in most Windows programs. Handy eh?
Unfortunately, there are additional problems with deleting directories caused
by AFIO's caching of directory handles in a central table — this happens
by default for all directories opened without write permissions and without
the file_flags::unique_directory_handle
flag. Explicit
close handle requests for these cached directories are ignored by AFIO, and
therefore AFIO may hold into existence a directory longer than might otherwise
be anticipated with the only way of forcing actual deletion being the destruction
of any reference to that directory, something difficult to achieve in larger
more complex codebases. Nevertheless, as it is the system which does the
deletion, you are guaranteed by Windows that the directory will eventually
be cleaned up some day, possibly in weeks or months on a long lived system.
If you don't want this, open directories with write permissions or the unique
directory handle flag.