[racket-dev] the preferences file under Windows

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Jan 13 16:57:49 EST 2011

Currently, the `get-preference' and `put-preferences' functions from
`racket/file' (which are used by DrRacket and other Racket tools) use
the write-to-temp-file-and-rename approach to atomic file update.
There's a lock to keep multiple writers from trying to update the file,
but no lock for readers.

As explained in my previous message, that doesn't work for Windows.

The writer lock is implemented by the existence of a lock file. That
is, a writer cannot proceed unless it is able to create the lock file,
and if some other process has created the lock file, then creation of
the lock file by other processes fails (so they know that the file is
locked). That much seems fine for Windows. The problem under Windows is
to prevent readers from interfering with a writer --- since having a
file open to read interferes with update --- the same as other writers.

Option 1: Readers could take the lock on the preferences file in the
 same way as writers.

The drawback of this option is that readers need write access to the
directory containing the preferences file, since the lock is
implemented by creating a file. Does that matter? It sounds wrong to
me, but maybe it's just fine.

Option 2: Use Windows file locking, and pick a new name for the
 preferences file under Windows.

It takes a few steps to explain the new-name part...

Not coincidentally, I recently added `port-try-file-lock?' and
`port-file-unlock' to Racket, so OS-supported file locking is an
option. (An evt form for locks would be nice, but OS APIs for file
locking make that difficult or impossible.)

Unfortunately, you can only hold the lock on a file if the file is open
--- and having the preferences file open is the root of the problem for
moving a new file into place. You can write to a file while holding a
lock, of course, but writing directly to the data file risks losing
information if the write is interrupted.

We could solve this sub-problem by having two files: the first holds
the preferences content, and the second exists only to be locked and
unlocked. That way, holding a lock doesn't interfere with replacing the
data file.

Unfortunately (again), the lock file has to exist alongside the data
file, and our existing preferences files are not accompanied by lock
files. It's no good assuming that you don't need the lock if there's no
lock file present, because the lock file might get created in between
the time that you try to use the lock file and the time that you try to
open the preferences file.

That's why this option includes picking a new name for the preferences
file (and its accompanying lock file) under Windows. The existing
preferences file would be used as a read-only fallback when no file
exists with the new preferences-file name.

Any opinions? Or does anyone see other options?

Posted on the dev mailing list.