ferrency has asked for the wisdom of the Perl Monks concerning the following question:
First, some background. As turnstep points out, this is Bad (tm):
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"; # zero-byte the file flock($FH, LOCK_EX); # and Then lock it...
Turnstep's tutorial presented the standard technique to fix this: use a separate "semaphore file" to keep track of locking: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
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.# 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
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).
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?# 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
Thank you for your comments on this.
Alan
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: A flock()alypse now
by BazB (Priest) on Jul 02, 2002 at 18:17 UTC | |
by ferrency (Deacon) on Jul 02, 2002 at 18:42 UTC | |
|
Re: A flock()alypse now
by Notromda (Pilgrim) on Jul 02, 2002 at 16:24 UTC | |
by ferrency (Deacon) on Jul 02, 2002 at 16:30 UTC | |
by Anonymous Monk on Jul 03, 2002 at 11:49 UTC | |
|
Re: A flock()alypse now
by belg4mit (Prior) on Jul 02, 2002 at 18:27 UTC | |
by ferrency (Deacon) on Jul 02, 2002 at 18:46 UTC | |
by tomhukins (Curate) on Jul 02, 2002 at 20:20 UTC | |
|
Re: A flock()alypse now
by perigeeV (Hermit) on Jul 02, 2002 at 20:43 UTC | |
|
Re: A flock()alypse now
by Aristotle (Chancellor) on Jul 03, 2002 at 14:38 UTC | |
by ferrency (Deacon) on Jul 03, 2002 at 14:51 UTC | |
|
Re: A flock()alypse now
by valdez (Monsignor) on Jul 03, 2002 at 14:43 UTC |