Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: Lock Effectivity

by demerphq (Chancellor)
on Apr 26, 2003 at 17:11 UTC ( [id://253386]=note: print w/replies, xml ) Need Help??


in reply to Lock Effectivity

Er, as far as I understand the way you have it wont work. You are opening the file in overwrite mode, and since the open happens before the lock and probably that locks are advisory on your os, you just clobber the lockfile, so your follow up lock suceeds because the file you are locking is not the same one (anymore) as the one the other process has locked (which you just deleted but it is holding open anyway).

So you have to open the file with something else, maybe '>>' or maybe '+<'. Im sure the article by Dominus that was suggested will help you sort it out.

And you should know that locking semantics vary from OS to OS. On Unix they are advisory, on Win32 they are compulsary. So for instance, what you did above would work just fine on Win32, but not on Unix.


---
demerphq

<Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

Replies are listed 'Best First'.
Re: Re: Lock Effectivity
by grantm (Parson) on Apr 26, 2003 at 20:03 UTC

    No, truncating a file does not cause any locks on it to be released. The pitfall Dominus was referring to here was that if the operation you're trying to lock is an edit of the file then this won't work since the act of opening it causes an 'edit' before you even ask for a lock. In the original poster's case though that's not a problem, since the lock file is being used as a semaphore to serialise access to a code section - the lock file will never have any contents to get clobbered. Looks good to me.

      No, truncating a file does not cause any locks on it to be released.

      Well actually I didnt say the lock would be released, just that the effect would be the same. But that was based on the presumption that the write behaved like an unlink, but your comment about the truncate (assuming it is correct, which on reflection I do) would invalidate that point anyway. (just explaining myself :-)

      The pitfall Dominus was referring to here was that if the operation you're trying to lock is an edit of the file then this won't work since the act of opening it causes an 'edit' before you even ask for a lock.

      The pitfall is worse when cross platform compatibility is considered. On Win32 trying to open a file for write that is locked is an 'Access is denied' error.

      In the original poster's case though that's not a problem, since the lock file is being used as a semaphore to serialise access to a code section - the lock file will never have any contents to get clobbered. Looks good to me.

      Ok, I can see your point about Unix. I still would say its bad code though, not only because of the Win32 issue, but because it just seems like a sloppy habit to get into. If you are going to utilize locking semantics, try to utilize the whole thing I would say. Also, one day you might change the semaphore file to actually hold data, then you might find the habit bites you. :-) But for me I can't do things like this anyway, so maybe I'm just rationalizing the necessity.

      Since you seem to know about this a bit, maybe you can explain something: it seems to me that there is no way to avoid a race condition if you want to have two processes that can do read/write on the same file on unix. Im assuming the logic would look like something like this

      my $fh; LOCK:{ open $fh,"+<",$file or open $fh,"+>",$file or last; flock($fh,LOCK_EX|LOCK_NB) or last; } $fh or die "$!";

      Isnt there a race condition when there is no file? The two process both see no file to read, and go to open if with write semantics, the first opens it even maybe gets the lock, then the second comes along, and does the same thing, truncating the file and then whether the lock fails or not the file state become indeterminate. Am I understanding this correctly? Does this mean that the only way to safely do this is to use a semphore file in the first place?

      Anyway, thanks for the heads up about truncate.


      ---
      demerphq

      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
        On Win32 trying to open a file for write that is locked is an 'Access is denied' error.

        Perhaps that's the case if another process has opened the file and used mandatory locking. However, this snippet certainly behaves as expected on Win32 (ie: a second instance successfully opens the locked file and waits for the lock to be released):

        use Fcntl qw(:flock); open(FILE, ">sem.lck") or die $!; print "Opened file\n"; flock(FILE, LOCK_EX) or die $!; print "Got lock\n"; sleep(10); close(FILE);

        I do exactly this on Win32 all the time.

        You're right, there is a potential race condition if you want to lock the file you're editing and you need to create it if it doesn't exist. The way around that is to use sysopen like this:

        sysopen(FILE, $path, O_RDWR|O_CREAT|O_EXCL) or die $!;

        The O_CREAT flag specifies that the file should be created if it does not exist and the O_EXCL specifies that the create should fail if the file does already exist. But this quickly gets complicated because you need to use one form if the file doesn't exist and another if it does. That's why it is so much simpler to use a separate file for locking than the file you're editing.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://253386]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-03-28 22:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found