Subject: | Log::Log4Perl::Appender::File destructor changes exit status of child |
Date: | Thu, 18 Apr 2013 14:38:24 -0700 |
To: | bug-Log-Log4perl [...] rt.cpan.org |
From: | Christopher Fitzner <chris [...] marchex.com> |
Hey there,
I just ran in what seems to be a bug in log4perl. I have some code where I'm
spawning a child process whose parent uses log4perl. The child inherits the
the parents log4perl filehandles and tries to close them upon exit. This close
fails but sets $? which changes the return status of the child. Specifically
this is happening to me when using cronolog to handle the log rotation. I'm
able to work around the issue by setting the filehandle to undef before exiting
the child.
I've confirmed that the behaviour still occurs in 1.40.
Here is some code to replicate this issue (sorry for the length):
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
use Errno;
use Log::Log4perl qw(:easy);
Log::Log4perl->Log::Log4perl::init('/tmp/logger.conf');
my $desired_child_count = 1;
our $logger = get_logger();
# list of active children
my %children = ();
while (1) {
# Figure out how many children are available to do work
my $children_available = detect_child_state();
if ($children_available) {
spawn_child();
}
print "$$: Main process sleeping for 10\n";
sleep 10;
}
exit 0;
sub detect_child_state {
local $!; # don't let waitpid() overwrite current error
while ((my $pid = waitpid(-1, POSIX::WNOHANG)) > 0) {
if (POSIX::WIFEXITED($?)) {
my $child_exit_status = POSIX::WEXITSTATUS($?);
if ($child_exit_status != 5) {
print "$$: child exited with abnormal status: $child_exit_status\n";
}
}
if (exists $children{$pid} ) {
delete $children{$pid};
}
}
return $desired_child_count - scalar keys %children;
}
sub spawn_child {
if (my $child_pid = fork()) {
$children{$child_pid} = 1;
}
elsif (defined $child_pid) {
print "$$: new child sleeping for 10\n";
sleep 10;
# here is the work around
# undef Log::Log4perl->appenders()->{CRONOLOG}->{appender}->{fh};
exit 5;
}
}
# here is the logger conf I'm using:
log4perl.rootLogger=DEBUG, CRONOLOG
##### STANDARD FILE LOGGING #####
log4perl.appender.LOGFILE=Log::Log4perl::Appender::File
log4perl.appender.LOGFILE.filename=/usr/bin/cronolog /tmp/test_logfile.log
log4perl.appender.LOGFILE.mode=append
log4perl.appender.LOGFILE.syswrite=true
log4perl.appender.LOGFILE.layout=PatternLayout
log4perl.appender.LOGFILE.layout.ConversionPattern=%d %H %c: %p [pid: %P] %l - %m%n
##### FOR USE WITH CRONOLOG #####
log4perl.appender.CRONOLOG=Log::Log4perl::Appender::File
log4perl.appender.CRONOLOG.filename=/usr/bin/cronolog /tmp/test_logfile.log
log4perl.appender.CRONOLOG.mode=pipe
log4perl.appender.CRONOLOG.layout=PatternLayout
log4perl.appender.CRONOLOG.layout.ConversionPattern=%d %H %c: %p [pid: %P] %l - %m%n
##### STDERR LOGGING #####
log4perl.appender.STDERR=Log::Log4perl::Appender::Screen
log4perl.appender.STDERR.layout=PatternLayout
log4perl.appender.STDERR.layout.ConversionPattern=%d %H %c: %p [pid: %P] %l - %m%n
##### STDERR LOGGING WITH COLOR #####
log4perl.appender.ColorScreen=Log::Log4perl::Appender::ScreenColoredLevels
log4perl.appender.ColorScreen.layout=PatternLayout
log4perl.appender.ColorScreen.layout.ConversionPattern=%d %H %c: %p [pid: %P] %l - %m%n