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

Hello. Does a lock still work correct, if I overwrite a locked file while it is locked? Illustration:

... sub do_log { ... sysopen my $fh, $logfile, O_RDWR|O_CREAT or do {...}; my $tmp_file = "${logfile}_tmp"; open my $tmp_fh, '>', "$tmp_file" or do {...}; if (flock $fh, LOCK_EX) { #exclusive lock while (<$fh>) { .. my $line = $_; .. print $tmp_fh $line, "\n"; } close $tmp_fh or die "Can't close tmp_file: $!"; move($tmp_file, $logfile); } close $fh or die "Can't close logfile $!"; #unlocks automatic }

Replies are listed 'Best First'.
Re: File lock question
by Anonymous Monk on Nov 06, 2009 at 13:55 UTC
    sysopen a lockfile, obtain lock on lockfile, then open your real file

      Ok, now I see the reason.

      ... sub do_log { ... sysopen my $fh, $logfile, O_RDWR|O_CREAT or do {...}; my $tmp_file = "${logfile}_tmp"; if (flock $fh, LOCK_EX) { #exclusive lock open my $tmp_fh, '>', "$tmp_file" or do {...}; while (<$fh>) { .. my $line = $_; .. print $tmp_fh $line, "\n"; } close $tmp_fh or die "Can't close tmp_file: $!"; move($tmp_file, $logfile); } close $fh or die "Can't close logfile $!"; #unlocks automatic }
        A second question: I call a sub check_nr_of_lines($nr_ofl, $arch_path, $logfile, $fh); When the max nr of lines in the logfile is reached, I want to write the half nr of lines in an archive file and delete them in the logfile. The other half should still be in the logfile. The following code does not work. It creates only an empty archive file, and changes nothing in the logfile. What must I change?
        ... sub do_log { ... sysopen my $fh, $logfile, O_RDWR|O_CREAT or do {...}; my $tmp_file = "${logfile}_tmp"; if (flock $fh, LOCK_EX) { #exclusive lock open my $tmp_fh, '>', "$tmp_file" or do {...}; while (<$fh>) { .. $nr_ofl = $.; my $line = $_; .. print $tmp_fh $line, "\n"; } ... check_nr_of_lines($nr_ofl, $arch_path, $logfile, $fh); ... close $tmp_fh or die "Can't close tmp_file: $!"; move($tmp_file, $logfile); } close $fh or die "Can't close logfile $!"; #unlocks automatic } sub check_nr_of_lines { my ($nr_of_lines, $arch_path, $logfile, $fh) = @_; if ( $nr_of_lines >= max_nr_of_lines_per_logfile ) { eval { mkpath($arch_path) }; if ($@) { ... } my $c = int($nr_of_lines / 2); open my $fh3, '>', "$arch_path/arch_test.log" or do { ... }; seek($fh, 0, 0); while (<$fh>) { print; if ($. <= $c) { print $fh3 $_; last; } print $fh $_; } } return; }