Locks for exclusive access to resources

T. William Wells bill at twwells.com
Wed Jun 14 15:26:48 AEST 1989


Well, I have a number of responses to my question.

>    1) Opening a lock file with O_EXCL.

Not present in V7, so not portable.

>    2) Using link, mknod, or mkdir to create the lock.  (But
>       aren't there some systems where mkdir isn't atomic?)

Mknod is not always available to the unprivileged (V7 again), and
mkdir isn't atomic on a number of systems. Link seems to be the
favorite.

Chris Torek says that link can misbehave when using NFS: if the link
request gets handled correctly but the reply to the requester gets
lost, NFS will retry the request. If the server has forgotten that it
succeeded in doing the link, it will retry the link, fail because the
link is already there, and return the failure. The effect is that the
link is created but the program thinks that it has not. (Is NFS really
that dumb? Stateless doesn't have to mean mindless!)

I see a way that this can be dealt with. Suppose that you first create
a file whose name is constructed from your system name and pid. In an
ideal world, that would be unique. Then do the link. If the link
fails, check the number of links to your file. If it is 2, you can
ignore the link failure. Does anyone see anything wrong with this?
(Other than the problem with the system name?)

>    3) Creating a file with permissions 000 (but this won't
>       necessarily work if one of the requestors' is root, right?)

As I said, this doesn't work with root. I suppose that one could do a
setuid and *then* do this; that means forking off a subprocess if one
wants to remain root. Any reason that won't work? (Never mind that it
is wasteful. I know that.) (And also: I know that 000 isn't
necessary. Anything that forbids writing would do.)

>    4) Using a server process to handle either the requests or the access.

No one had much good to say about this; the comments boiled down to:
"how"? Here's one way: I create a file from my machine name and pid.
I wait till it goes away. When it does, I proceed. When I'm done, I
create another file with some fixed name, just to let the server know
that I'm done. To have the server perform the request, I would put
the request data into the file and not exit till that file is
deleted. (To tie up the pid.)

Of course, this involves busy loops in both the user process and the
server; I don't recommend it. I just thought I'd point out that it is
possible to use this method, even with vanilla Unix.

The following people contributed to the above:

Chris Torek             uunet!mimsy!chris
Gordon Burditt          gould!sun!Central!sneaky!gordon
John F. Haugh II        uunet!cs.utexas.edu!rpp386.Cactus.ORG!jfh

Arndt Jonasson, uunet!mcvax!zyx.ZYX.SE!arndt, suggested a variation
on the link method: instead of linking a file, *unlink* it. The idea
that the default state is that the lock file exists. When you want the
resource, you *un*link the lock file. If that succeeds, you go. If
not, you fail. This should also have the same problem as the link
solution: you can get back a failure when the unlink actually
succeeds. I can't think of a reliable method of detecting this,
however.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill at twwells.com



More information about the Comp.unix.wizards mailing list