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

After reading the great article on file locking I found here, I am trying to open a file, flock it, read it and then write to it. I am trying to do both the read and write under one flock so that there is no possiblility of someone opening the file between the read and write. I have cut the code down to show the intent. I also know that, or think that, when opening the file with the +>, the file will be overwritten when I do the print thing? Anyway, I really appreciate any help on this. The following works fine:
open(INFILE, "file.htm"); flock(INFILE, 1); @lines=<INFILE>; close(INFILE); open(OUTFILE, "+>$file.htm"); flock(OUTFILE, 2); print OUTFILE "stuff"; close(OUTFILE);
The following does NOT work
open(OUTFILE, ">$file.htm"); flock(OUTFILE, 2); @lines=<OUTFILE>; print OUTFILE "stuff"; close(OUTFILE);

Replies are listed 'Best First'.
Re: flock issue
by turnstep (Parson) on Mar 15, 2001 at 03:49 UTC

    You must open a file with write permission in order to secure an exclusive lock. Also, you should be checking the result of your open calls. You can use the read/write mode "+<" to open it for writing without clobbering anything that is there. Use seek to move about once you have opened it so.

Re (tilly) 1: flock issue
by tilly (Archbishop) on Mar 15, 2001 at 15:40 UTC
    When I was first getting the hang of flock I found it very useful to have a sample script like the above which at each stage printed what stage it was at, waited for input, and then continued. Running this in multiple terminals allowed me to walk through various possible race conditions and see what exactly was happening.

    I recommend trying that.

    An incidental note that you are completely missing above, if you will be writing a shorter string than was there before it is important that you truncate the file.

    Incidentally for working code that puts all of this together you should try Simple Locking. I should note that I generally prefer sentinel files as an approach. They allow you to use flocks to produce mutexes around logical units of actions, which may not be just limited to manipulations of a single file.

Re: flock issue
by tomhukins (Curate) on Mar 15, 2001 at 21:25 UTC

    One potential problem that hasn't been mentioned yet, is that the process may die during the print OUTFILE action, causing some data at the end of the file to be lost. I usually write to a temporary file then rename this temporary file to replace the original file. Renaming is atomic on every system that I'm aware of.

    For example:

    # At this point I have created some sort of lock to ensure # nobody else is going to read or write $infile_name while (<INFILE>) { # Using read instead of <INFILE> would be more e +fficient print TEMPFILE; } close TEMPFILE rename $temp_filename, $infile_name or die # Remove the lock here
Re: flock issue
by airman (Initiate) on Mar 15, 2001 at 04:06 UTC
    Hum, if I use +< it workie better. Thanks anyway it works now.