Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Question about Flock and die

by acarvalh (Novice)
on Apr 05, 2003 at 19:46 UTC ( [id://248329]=perlquestion: print w/replies, xml ) Need Help??

acarvalh has asked for the wisdom of the Perl Monks concerning the following question:

After looking at the Monks' flock tutorial and the man pages on the sytem, I tried the following:
use Fcntl qw/:flock/; OPEN(LOCKFILE, ">.lockfile") || die "another process already running"; flock LOCKFILE, LOCK_EX; long_and_boring_function_call(); close LOCKFILE; #close unlocks file
Some tutorials say to die at the open statement. Others tutorials say to die at the flock statement. However the perldocs (perlfunc page) say that flock will spin until it gets a lock. Thus it will never fail (and never die).

I've tried to die at the open statement, and the flock statement; in both situations it does the "spin until it's free" behaviour.It waits for the first process to stop, then successfully obtains a lock.

So what am I doing wrong? How can one use flock to ensure that the process **dies**? (Or is there another way?)

Any enlightenment on this simple problem is most appreciated. :-)

April

edited: Sat Apr 5 21:46:42 2003 by jeffa - added code tags

Replies are listed 'Best First'.
Re: Question about Flock and die
by grantm (Parson) on Apr 05, 2003 at 19:54 UTC

    If you want flock to return immediately rather than wait for a lock to become free, you need a 'non-blocking' lock. eg:

    flock LOCKFILE, LOCK_EX | LOCK_NB or die;

    A trick I learned from Dominus is to open $0 for reading and lock it rather than creating a separate file for locking.

      Some little disagreement:-) (Overall, your answer is obviously correct, no doubt about that)

      1. Strictly speaking, locking $0 has no difference from locking a "separate" file, as $0 is still a separate lock file, not a direct lock on the file under concern itself.
      2. A caveat with this approach (to lock $0) is that, it adds a restriction that, in order to make the lock work, multiple users have to run a single copy of the script from the same location, which is not true all the time.
        locking $0 has no difference from locking a "separate" file

        Quite true, but my words were "creating a separate file" :-)

        Also, I was reading between the lines and (possibly incorrectly) came to the conclusion that the OP was trying to prevent simultaneous access to a script. If that was the goal but there were multiple copies of the script or mutliple names (links) then no, the $0 approach wouldn't work.

Re: Question about Flock and die
by dug (Chaplain) on Apr 05, 2003 at 19:58 UTC
      That is great information but some of the things stated there are not true.

      Slide 4: Trap #1: LOCK_UN
      States that "flock FH, LOCK_UN" doesn't flush the buffer -- not true. This may have been the case in older versions of Perl but not in the current ones. From 'perldoc -f flock'
      "To avoid the possibility of miscoordination, Perl now flushes FILEHANDLE before locking or unlocking it."

      Slide 7: Trap #2: Failing to check for failure
      The thing that threw me here is the example. It states that flock() may fail if FH is not open. True. But then it also states that the file will be modified because flock() failed. Not true. How are you going to modify the file if FH is not defined? ;)
      The example that should've been there, in my opinion, is the one involving interrupted system calls. If a program is waiting for a lock and it receives a signal, this will result in flock() returning an error and unless the program checks the return value of flock(), it'll happily proceed with its job even though it doesn't really have a lock.

      I don't mean to be picky. Please accept this a constructive critisism. :)

      --perlplexer
          States that "flock FH, LOCK_UN" doesn't flush the buffer -- not true.

        Well, it *is* true for many folks ;-) And if one is writing a module for public consumption (or for any environment that the potentially don't have complete control of), it is best to be safe. Heating up the pipes of a filehandle that already has buffering turned off can't hurt in this case, it can only ensure safety.

          It states that flock() may fail if FH is not open. True. But then it also states that the file will be modified because flock() failed. Not true. How are you going to modify the file if FH is not defined? ;)

        The point of Trap #2 is that the flock() system call may fail for some reason. If one doesn't check for a failure of the system call, one could end up modifying a file that they couldn't obtain a lock on, which probably wouldn't be the intended result.

        -- dug
Re: Question about Flock and die
by Lhamo Latso (Scribe) on Apr 05, 2003 at 19:56 UTC

    Use LOCK_NB for a not_blocking call to flock. That means, don't wait on a lock to free up. Here is some code that I use to try 10 times.

    my $db = tie %HoA, 'DB_File', $path, O_RDWR | O_CREAT, 0666, $DB_HA +SH or die "[Error processing $path ] $!"; my $fd = $db->fd; open DBM, "+<&=$fd" or die "Could not dup DBM for lock: $!"; # now try to lock it my $success; my $tries = 0; while ($tries++ < 10) { last if $success = flock (DBM, LOCK_EX|LOCK_NB); print p("Waiting for $lock_type lock on AddressBook file..."); sleep(1); # wait a second } undef $db;
Re: Question about Flock and die
by nothingmuch (Priest) on Apr 05, 2003 at 20:16 UTC
    open will fail if there are no permissions, or the file does not exist, or something of the sort. flock will fail if an error occured, or if a non blocking request for a lock failed. I assume that should the filehandle have not been opened by open, then perhaps flock will fail if there was an error anyway. But you'll probably lose the content of $!.

    Opening a locked file will not raise an error, as on *nix locks are advisory, and not mandatory. Your open statement will actually fail only if you haven't read access to the file, or the directory in case it doesn't exist. Other than that there is no reasonably expectable error, and what you're trying to acheive is done, as the others noted, with non blocking flock.

    -nuffin
    zz zZ Z Z #!perl
Re: Question about Flock and die
by converter (Priest) on Apr 06, 2003 at 00:25 UTC

    What if your open succeeds, but flock fails? You've already created a new lockfile. This probably won't hurt anything if the lockfile is empty, but if you should later decide to write something to the lockfile, a pid for example, you'll have a bug that will probably be very difficult to track down.

    dug mentioned File Locking Tricks and Traps (dug++), the Trap #3: Shutting the Barn Door etc. slide explains the problem and the slide that follows shows a better way to open the file.

Re: Question about Flock and die
by Coruscate (Sexton) on Apr 05, 2003 at 22:46 UTC

    Just to mention: yes, you should most definitely die() at the open statement. As for the flock statement, I usually add on a die() just in case. I don't know why, I just do :)


    If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, please reply to this node or /msg me to inform me as to what is wrong with the post, so that I may update the node to the best of my ability.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-26 02:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found