J
J. Romano
Hi,
Since flock() calls have become such a hot topic recently, I've
been wondering how I can lock a file before any changes are made. Let
me provide an example:
Say I have a file with one-thousand lines of text. (If you want to
follow along, you can quickly create one with the command:
perl -le "print 'text line' foreach (1 .. 1000)" > file.txt
). Now I invoke the "interactive Perl interpreter" with the line:
perl -de 1
Now I want to open the file for writing, lock it, and then change
its contents once I acquire the lock. Normally I would do it like
this:
open(FILE, ">file.txt") or warn "Could not open: $!";
flock(FILE, LOCK_EX);
print FILE "New text lines\n" x 50;
close(FILE); # closes the file and releases the lock
This looks acceptable in that I don't modify anything until AFTER I
acquire the lock, but when I execute that first line in the
interpreter (and before I execute the next line that has the flock()
call) I can see in another window that the file's contents get cleared
out.
But that's not what I want! I don't want the file to be modified
in any way until I get the lock, but I can't get the lock until after
I open the file, and by that time the contents have already been
modified!
Is there any way to open a file for writing that won't change its
contents before I use flock()?
In case anyone is interested, here is my "perl -v" output:
This is perl, v5.8.2 built for MSWin32-x86-multi-thread
(with 25 registered patches, see perl -V for more detail)
I did find one work-around... instead of opening the file with ">",
I can open it with "+<", then use flock(), then seek to the beginning
of the file, like this:
open(FILE, "+<file.txt") or warn "Could not open: $!";
flock(FILE, LOCK_EX);
seek(FILE, 0, 0); # go to the beginning of the file
print FILE "New text lines\n" x 50;
truncate(FILE, tell(FILE)); # remove extra old data
close(FILE); # closes the file and releases the lock
Not only is this approach unfavorable because it uses extra lines of
code that seem unnecessary, but according to "perldoc -f truncate",
calling truncate() "produces a fatal error if truncate isn't
implemented on your system," which makes me think that it's not all
that portable.
Does anyone have a better way to lock a file before it's modified?
Thanks in advance.
-- Jean-Luc
Since flock() calls have become such a hot topic recently, I've
been wondering how I can lock a file before any changes are made. Let
me provide an example:
Say I have a file with one-thousand lines of text. (If you want to
follow along, you can quickly create one with the command:
perl -le "print 'text line' foreach (1 .. 1000)" > file.txt
). Now I invoke the "interactive Perl interpreter" with the line:
perl -de 1
Now I want to open the file for writing, lock it, and then change
its contents once I acquire the lock. Normally I would do it like
this:
open(FILE, ">file.txt") or warn "Could not open: $!";
flock(FILE, LOCK_EX);
print FILE "New text lines\n" x 50;
close(FILE); # closes the file and releases the lock
This looks acceptable in that I don't modify anything until AFTER I
acquire the lock, but when I execute that first line in the
interpreter (and before I execute the next line that has the flock()
call) I can see in another window that the file's contents get cleared
out.
But that's not what I want! I don't want the file to be modified
in any way until I get the lock, but I can't get the lock until after
I open the file, and by that time the contents have already been
modified!
Is there any way to open a file for writing that won't change its
contents before I use flock()?
In case anyone is interested, here is my "perl -v" output:
This is perl, v5.8.2 built for MSWin32-x86-multi-thread
(with 25 registered patches, see perl -V for more detail)
I did find one work-around... instead of opening the file with ">",
I can open it with "+<", then use flock(), then seek to the beginning
of the file, like this:
open(FILE, "+<file.txt") or warn "Could not open: $!";
flock(FILE, LOCK_EX);
seek(FILE, 0, 0); # go to the beginning of the file
print FILE "New text lines\n" x 50;
truncate(FILE, tell(FILE)); # remove extra old data
close(FILE); # closes the file and releases the lock
Not only is this approach unfavorable because it uses extra lines of
code that seem unnecessary, but according to "perldoc -f truncate",
calling truncate() "produces a fatal error if truncate isn't
implemented on your system," which makes me think that it's not all
that portable.
Does anyone have a better way to lock a file before it's modified?
Thanks in advance.
-- Jean-Luc