If flock() call times out in _lock_handle the $h handle is closed (close($h)) but the
attribute$self->{'h'} is not reset to undef. The following log() calls fail with the warning
messages:
====
flock() on closed filehandle $h at /opt/perl-
5.8.8/lib/vendor_perl/5.8.8/Log/Dispatch/FileShared.pm line 210.
flock() on closed filehandle $h at /opt/perl-
5.8.8/lib/vendor_perl/5.8.8/Log/Dispatch/FileShared.pm line 238.
seek() on closed filehandle $h at /opt/perl-
5.8.8/lib/vendor_perl/5.8.8/Log/Dispatch/FileShared.pm line 256.
print() on closed filehandle $h at /opt/perl-
5.8.8/lib/vendor_perl/5.8.8/Log/Dispatch/FileShared.pm line 139.
flock() on closed filehandle $h at /opt/perl-
5.8.8/lib/vendor_perl/5.8.8/Log/Dispatch/FileShared.pm line 144.
====
close($h);
should be replaced with
$self->_close_handle();
Attached:
script that reproduce the error,
script output,
diff file that fixed the problem
Subject: | FileShared.pm.diff |
*** Log/Dispatch/FileShared.pm.orig Fri Feb 17 13:11:55 2012
--- Log/Dispatch/FileShared.pm Fri Feb 17 13:12:21 2012
***************
*** 240,246 ****
};
alarm 0;
if ($@) {
! close($h);
if ($@ eq __PACKAGE__ . ".ALRM\n") {
# This is a dilemma too.
warn(sprintf("Timeout waiting for lock on '%s'.", $self->{'filename'}));
--- 240,246 ----
};
alarm 0;
if ($@) {
! $self->_close_handle();
if ($@ eq __PACKAGE__ . ".ALRM\n") {
# This is a dilemma too.
warn(sprintf("Timeout waiting for lock on '%s'.", $self->{'filename'}));
Subject: | log_dispatch_fileshared.log |
Message body not shown because it is not plain text.
Subject: | log_dispatch_fileshared.pl |
#!/usr/bin/perl -w
use strict;
use Fcntl qw(:DEFAULT :flock);
use Log::Dispatch::FileShared;
my $file = "/tmp/log_dispatch_fileshared.lock";
unlink $file;
defined (my $pid = fork()) or die "fork failed";
if ($pid == 0) {
child();
exit;
}
parent();
wait();
sub parent{
open my $h, ">>", $file or die "open >> $file failed";
printf "parent: file $file opened, waiting 1s\n";
sleep 1;
flock($h, LOCK_EX) or die "flock failed: $!";
printf "parent: locked for 3s\n";
sleep 5;
flock($h, LOCK_UN);
printf "parent: unlocked\n";
}
sub child {
my $output = Log::Dispatch::FileShared->new(
name => 'test',
min_level => 'info',
filename => $file,
) or die "Log::Dispatch::FileShared->new failed";
for my $i (1 .. 7) {
print STDERR "child:$$: ->log('info',$i)\n";
$output->log( level => 'info', message => "$$: test message: $i.\n" );
print STDERR "child:$$: ->log('info',$i): done\n";
sleep 1;
}
}