[comp.lang.perl] Locking files across NFS

fingerhu@ircam.fr (Michel Fingerhut) (01/12/91)

It would be neat to have a builtin lockf call (now that I got flock to work,
thanks, Larry).

Michael

tchrist@convex.COM (Tom Christiansen) (01/12/91)

From the keyboard of fingerhu@ircam.fr (Michel Fingerhut):
:It would be neat to have a builtin lockf call (now that I got flock to work,
:thanks, Larry).

You should be able to use fcntl for lockf.  See the man pages on
those functions.

--tom
--
"Hey, did you hear Stallman has replaced /vmunix with /vmunix.el?  Now
 he can finally have the whole O/S built-in to his editor like he
 always wanted!" --me (Tom Christiansen <tchrist@convex.com>)

worley@compass.com (Dale Worley) (01/16/91)

   X-Name: Michel Fingerhut

   It would be neat to have a builtin lockf call (now that I got flock to work,
   thanks, Larry).

Beware that Sun's locking daemons don't always work correctly.

Dale Worley		Compass, Inc.			worley@compass.com
--
"How many men you got 'ere, Colonel?"
"Oh, 7,000 infantry, 600 artillery, and 2 divisions of paratroops."
"Paratroops, Dino!"  "It'd be a shame of someone was to set fire to dem."
"Set fire to them?!"
"Fire's 'appen, Colonel."  "Fing's burn..."

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (01/22/91)

In <1991Jan15.203815.25561@uvaarpa.Virginia.EDU> worley@compass.com
(Dale Worley) writes:

>Beware that Sun's locking daemons don't always work correctly.

Sun's locking daemons have never worked correctly whenever I have tried
them.  I finally decided that it would be better to rely on the
standard reliable UNIX method:  create a lock file.  I used this
successfully for a while.  Then discovered with a shock that NFS has no
mechanism for ensuring exclusive creation of a file even if the O_EXCL
flag is given to open().  NFS does make symbolic links links correctly.
I think it may even make hard links correctly.  The following algorithm
assumes that hard links are correctly created atomically.

So the only reliable mechanism that exists to do file locking over NFS
is the following or its equivalent.  if you want reliable locking that
is reasonably immune to locks being held by dead processes, I see no
way of making this algorithm any simpler.

int get_a_lock()
{
     if (create(symlink called MUTEX that points anywhere) == failed) {
	die("serious problem -- can't create MUTEX");
     }
     /* reach here when gained exclusive access */
     attempts = 0;
     while (++attempts < SOME_LIMIT) {
	if (create(some unique temp file called $TMP) == succeeded) {
	   to $TEMP write our host name and pid;
	   break; /* done with while loop */
	} else {
	   sleep (a few seconds);
	}
      }
      if (attempts == SOME_LIMIT) {
	 die("serious problem -- can't create mutex");
      }
   try_again:
      {
        static int loop_breaker;
	if (++loop_breaker > SOME_OTHER_LIMIT) {
	   loop_breaker = 0;
	   unlink($TMP);
	   unlink(MUTEX);
	   return LOCK_ATTEMPT_FAILED; /* or die here */
	 }
      }
      if (create(link from $TMP to LOCK) == success) {
	 /* we have the lock!! */
	 unlink($TMP);  /* not needed, link is now LOCK */
	 unlink(MUTEX); /* not needed, done its work */
	 return GOT_A_LOCK;
      } 
      /* failed to create link;  see if it's a stray link */
      if (LOCK doesn't exist) {
	 unlink($TMP);
	 unlink(MUTEX);
	 die("serious problem, LOCK nonexistent but can't create");
      }
      if (read(contents of LOCK) == failed) {
	 unlink($TMP);
	 unlink(MUTEX);
	 die("serious problem, can't read existing LOCK");
      }
      lock_host = name of host read from LOCK;
      lock_pid = pid read from LOCK;
      if (lock_host is our current host) {
	 /* see if process still alive */
	 if (kill(pid, SIG_SEE_IF_IT'S_THERE) == ENO_SUCH_PROCESS) {
	    unlink(LOCK); /* must have been stray */
	    goto try_again;
	 } 
      }
      /* LOCK is already held by existing process on this host
      or is on some other host */
      return LOCK_ATTEMPT_FAILED;
}
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

thurlow@convex.com (Robert Thurlow) (01/23/91)

In <2909@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:

>Sun's locking daemons have never worked correctly whenever I have tried
>them.

Sounds a bit harsh to me.  I have a few problems with the robustness
of the daemon, but it does seem to work.  I have high hopes for the
NFSSRC 4.1 version, mainly because I haven't seen the source code yet :-)

>I finally decided that it would be better to rely on the
>standard reliable UNIX method:  create a lock file.  I used this
>successfully for a while.  Then discovered with a shock that NFS has no
>mechanism for ensuring exclusive creation of a file even if the O_EXCL
>flag is given to open().

Correct.  open() maps in an odd way to the over-the-wire ops, and if you
do get the idea that you can create a node, the create op doesn't have
an exclusive flag over-the-wire.  This is one of the top three protocol
bugs in the product.  I'm personally more frustrated by the lack of an
over-the-wire access() op, myself.

>NFS does make symbolic links links correctly.
[code to do locking with symlinks and hard links.]

Guess what?  It won't be reliable all the time, either.  If you have a
server which doesn't detect duplicate requests properly (and I think
anything based on NFS 3.2 did this), when the server gets slow, it will
get a pair of these requests due to timeouts and will return an error
on the second attempt.  *Most* won't do this, but I don't really get
the feeling that that *most* is more bankable in general than "lockf()
works *most* of the time."

[I've redirected followups to comp.protocols.nfs as we've drifted a bit.]

Rob T
--
Rob Thurlow, thurlow@convex.com or thurlow%convex.com@uxc.cso.uiuc.edu
"The Canadian rock singer, Ronnie Hawkins, has it all figured out.  'Believe
 in God?' he says, "Man, I believe in God like nobody else.  It's the fucking
 ground crew I don't trust." - "Running Risks", Angela Issajenko