Help: using msvcrt for file locking

Bengt Richter bokr at accessone.com
Tue Aug 28 03:20:42 CEST 2001


On Mon, 27 Aug 2001 06:14:56 GMT, Sheila King <sheila at spamcop.net> wrote:
[...]
>
>Actually, I think what happens with Windows98, is that there is only
>exclusive lock. No shared locking (which is what one would want for
>reading). So, I could change the name of the file when a write process
>wants to acquire it. Otherwise, if the un-renamed file is there, it is
>OK to read from it. Do you think this type of approach would work for
>the reading part only? 
>
Yes, but there's a problem, because you need to be able to distinguish
2+n states of a file: (1) not open for anything (2) open for readonly
n>0 times (3) open for exclusive writing.

A prospective writer must be able to distinguish (1) from (2).
Renaming only by writer would be ok to stop *additional* prospective
readers from opening the file but the prospective writer must also
have a way of knowing when all *current* readers have closed the file.

BTW, note that renaming will fail with permission denied on win32
if the file is open, but not so on unix with its separation
of names vs inode file info, so on unix a file could be in state
(2) and you'd have no indication if you leave the name unchanged
for (1) and (2), and don't have another indication.

A writer has to be able watch for the count of readers to go to zero
one way or another. Perhaps you could have readers create individual
expiring read-lock files named by appending their os.pid() numbers
plus time tag to the name of the file to lock. Then the writer could
watch for all those to disappear or expire.

This only applies for high traffic on win32, but since on win32 the
writer can't assume ability to rename as a mechanism for preventing
additional readers when the file is already open (it get permission
denied, unlike unix), perhaps if the writer process creates its own
write-lock file as a first step, then potential readers could defer
creating their read-lock files if they see that, and existing ones
would cycle out or expire, and the writer could  rename and open the file.

For unix the write-lock file would be a waste, since renaming will succeed
unless the file is in orphan form. And unless you are fighting a humongous
swarm of readers all interested in one file on win32, it shouldn't hurt
to leave it out there either.

Note that the atomicity of renaming is critical to making this work. E.g.,

reader        writer
--------    ------------
[ck wlock]      .           <-not really needed except high traffic win32?
   .         [set wlock]    <-ditto
   .         rename         <-not safe to eliminate
   .         ck rlocks
   .         open for w
set rlock       .
open for r      .
   .         write
read ??

If writer renames or attempts to rename the base file just before
checking rlocks, then the reader's open will fail or succeed depending on
whether it happened before the rename. If the open for r succeeds, it means
that it has also set rlock before the rename, so the writer will see that and
not open for w. If it fails, then the reader failed to complete access and
should delete its rlock (which the writer would be monitoring). In the
open failure case, it would not matter if the failing reader's rlock was seen
or not by the writer. However, any prior reader's rlock that actually
succeeded in opening the file would be seen.

On win32 the rename would raise an exception if the reader had succeeded,
so the rlock check could effectively be accomplished just with that, but
as mentioned, that's not true on unix, so it needs to be in the waiting
loop for win32 with a try/except wrapper, and the rename should not
be repeated if it succeeds, as it normally will on unix.

It'd be nice if the builtin open had an option for exclusive access within
a specified timeout for trying ;-)

HTH




More information about the Python-list mailing list