Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Lock Effectivity

by Gorby (Monk)
on Apr 26, 2003 at 12:51 UTC ( #253350=perlquestion: print w/ replies, xml ) Need Help??
Gorby has asked for the wisdom of the Perl Monks concerning the following question:

Hello wise monks. I'd just like to know if file locking in perl is fail safe. If I have something like this in my code:
sub get_lock { open(SEM, ">$semaphore_file") || die "Cannot create semaphore: $!"; flock(SEM, LOCK_EX) || die "Lock failed: $!"; } sub release_lock { close(SEM); } $semaphore_file="semfile"; get_lock(); #Do something here release_lock;
Would any other instance of the same program be able to get passed the get_lock(); line without obtaining a lock first? Shouldn't the get_lock(); line make all instances of the same program "wait their turn" to get a lock before proceeding so that only one instance of the program gets to "Do something here" at a time? Thanks in advance.

Comment on Lock Effectivity
Download Code
Re: Lock Effectivity
by Improv (Pilgrim) on Apr 26, 2003 at 13:03 UTC
    Looks good to me. Provided that you're not locking files over a broken version of NFS, or something similar, no other instances of that program should be able to enter the critical section at the same time another is.
Re: Lock Effectivity
by Limbic~Region (Chancellor) on Apr 26, 2003 at 13:59 UTC
    Gorby,
    Take a look at this thread by Dominus. There are a lot of pitfalls associated with file locking. Some of the ones I have pointed out is that on a *nix system, it is possible to delete a file that has an exclusive lock. It is also possible to write to a file with an exclusive lock. The reason is that unless the process requests a lock before doing its damage, the OS will allow it to continue on its merry way.

    Now if you know your program is the only one that will be dealing with the semaphore file and you have coded a proper locking mechanism - then you are all set.

    Cheers - L~R

Re: Lock Effectivity
by demerphq (Chancellor) on Apr 26, 2003 at 17:11 UTC

    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...

      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...

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://253350]
Approved by valdez
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2014-10-25 07:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (142 votes), past polls