http://www.perlmonks.org?node_id=659032

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

Hi, I have a program which modifies a file in place using a temporary file
open(OLD, "< $old") or die "can't open $old: $!"; open(NEW, "> $new") or die "can't open $new: $!"; my @array = <OLD>; my $required_element_details = shift(@array); foreach my $remaining_details (@array) { print NEW "$remaining_details"; } close(OLD) close(NEW) rename($new, $old)
Problem is this file can be accessed at the same time by the same program so the reading and writing process needs to be locked. Have tried:
open(OLD, "< $old") or die "can't open $old: $!"; open(NEW, "> $new") or die "can't open $new: $!"; flock (OLD, 2); flock (NEW, 2); [continue as before including renaming the file before the filehandles + are closed]
But this doesn't work when both programs are trying at the same time, instead both programs read the same initial element (and write the same results). Any suggestions? Colin

Replies are listed 'Best First'.
Re: file lock and update
by McDarren (Abbot) on Dec 26, 2007 at 14:56 UTC
    Hi Colin,

    You probably want to use sysopen rather than open. The canonical way to do this (on a single output file) is something along the following lines:

    use Fcntl qw(:DEFAULT :flock); sysopen(OUT, $outfile, O_WRONLY | O_CREAT) or die "Cannot open $outfile for writing:$!\n"; flock(OUT, LOCK_EX) or die "Cannot get a lock on $outfile:$!\n"; truncate(OUT, 0) or die "Cannot truncate $outfile:$!\n";
    There are a couple of very good discussions regarding file locking in the Camel (3rd Ed.). If you happen to have a copy, look in Chapters 16.2.1 and 23.2.2.

    Otherwise, you can refer to the docs for sysopen and flock.
    perldoc -q lock also gives some useful examples.

    Hope this helps,
    Darren :)

Re: file lock and update
by mickeyn (Priest) on Dec 26, 2007 at 13:11 UTC
Modifying a file in place (was Re: file lock and update)
by roboticus (Chancellor) on Dec 26, 2007 at 15:21 UTC
    CColin:

    A minor nit in terminology: Your program doesn't modify the file in place. "Modify in place" means to open the file in read/write mode and alter the file without creating a new copy. (Not terribly safe for many applications, though!) Here's an example of modifying a file in place:

    $ cat 659032.pl #!/usr/bin/perl -w use warnings; use strict; # Open in Read/Write mode and modify it in place open FH, "+<", "a_file.txt" or die "Can't open file!"; print FH "Foo bar baz!"; close FH; $ cat a_file.txt Now is the time for all good men to come to the aid of their party. $ perl 659032.pl $ cat a_file.txt Foo bar baz!ime for all good men to come to the aid of their party. $
    ...roboticus