I need to create a file that is locked against reads, at the point of creation, so that other processes that may go looking for this file do not start reading it, before it has been completely written.
I know that I can create and then lock it, but I'm concerned that this leaves me open to a race condition.
Or am I worrying about nothing here? If I have a file open for writing and then open it for reading with another process, will the reading process never see an EOF until the writing process closes the file?
There's is a race condition with >
and >>
, but it can be circumvented using +<
.
# >
open(my $fh, '+<', $qfn) or die $!;
flock($fh, LOCK_EX) or die $!;
truncate($fh, 0) or die $!;
...
# >>
open(my $fh, '+<', $qfn) or die $!;
flock($fh, LOCK_EX) or die $!;
seek($fh, 0, SEEK_END) or die $!;
...
There is also a race condition in the scenario you describe.
Writer Reader
========================= =========================
- opens file
- opens file
- locks file
- obtains lock on file
- locks file [blocks] - reads the file [empty]
- closes and unlocks file
- obtains lock on file
- writes to file
- writes to file
- closes and unlocks file
A common strategy to avoid this problem is to have the writer
rename
the file into the directory the reader monitors when the file is complete. rename
is an atomic action, so the file will appear fully formed in the directory the reader monitors. This requires the cooperation of the writer, but the best solutions will.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With