Turnstep presents a bunch of great information in his File Locking tutorial. However, there is at least one file locking technique which I have not seen anyone use on perlmonks. I'm not sure if that's because there's something wrong with it, or because I haven't been looking hard enough.

First, some background. As turnstep points out, this is Bad (tm):

open my $FH, ">the_file"; # zero-byte the file flock($FH, LOCK_EX); # and Then lock it...
And, since you need to give flock() a file handle, it's not completely obvious how to read, process, and then write a file while maintaining a lock on it. This is an example of how Not to do it:

open my $FH, "the_file"; # open for reading flock($FH, LOCK_SH); # lock it my @lines = <$FH>; # read it open $FH, ">the_file"; # open for writing: LOCK DROPPED. # Now someone else picks up the lock and finds an empty # file. When they're finished, flock($FH, LOCK_EX); # lock it again push @lines, "new line\n"; # process the lines print $FH for (@lines); # write them out close $FH; # close and drop lock
Turnstep's tutorial presented the standard technique to fix this: use a separate "semaphore file" to keep track of locking:

# Open a different file as a semaphore lock open my $SEM, ">the_file.semaphore"; flock($SEM, LOCK_EX); # lock it # then process the Real File open my $FH, "the_file"; my @lines = <$FH>; # read it # because we never fiddle with $SEM, we still have a lock open $FH, ">the_file"; # open for writing. push @lines, "new line\n"; # process the lines print $FH for (@lines); # write them out close $FH; # close the file close $SEM; # close and unlock semaphore
The main problem with this is, it "doesn't play well with others." If you are trying to cooperate with other programs which you have no control over, you may not have the luxury of being able to use a semaphore file with a different name.

To me, the solution to this seems obvious. But I haven't seen this on perlmonks before, so my paranoia makes me think there's something wrong with it. I use the file itself as its own "semaphore file." This should work fine, since flock() locks are only advisory, not forced locks (that is, you can choose to ignore them and the OS won't even slap you on the wrist for it).

# Open the file for locking purposes only open my $SEM, "the_file"; flock($SEM, LOCK_EX); # lock it # Process it open my $FH, "the_file"; my @lines = <$FH>; open $FH, ">the_file"; push @lines, "new line\n"; print $FH for (@lines); close $FH; close $SEM; # close and unlock semaphore
Now we don't have any race conditions, because we're not doing anything with the_file before we get the lock, and we're not dropping the lock before we're completely finished with processing the file. We also behave well in relation to other programs which may be acquiring locks on the same file. We aren't creating stray lock files lying around which may need to be cleaned up periodically. It seems better in almost every respect... but does it work?

Thank you for your comments on this.

Alan


In reply to A flock()alypse now by ferrency

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.