Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to create a file that is locked at the point of creation, in Perl?

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?

like image 616
Dancrumb Avatar asked Dec 02 '22 02:12

Dancrumb


1 Answers

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

  1. create the file in a temporary directory, and then
  2. 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.

like image 81
ikegami Avatar answered Dec 04 '22 21:12

ikegami