#!/usr/bin/perl -w BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # test case for regression where the .LCK file was unlinked in DESTROY(), # allowing multiple processes to enter the critical section at the same time. use strict; use warnings; use Path::Tiny; use IO::Handle; use Test::More; my $pid = fork; if (!defined $pid) { plan skip_all => 'fork() does not work on this platform'; } elsif ($pid == 0) { # child exit; } else { # parent waitpid $pid, 0; } plan tests => 1; use Log::Dispatch::FileRotate; shim_logit_delay(); my $tempdir = Path::Tiny->tempdir; my $warnings_file = $tempdir->child('warnings.txt')->stringify; $pid = fork; if (!defined $pid) { die "fork failed: $!\n"; } if ($pid == 0) { run_processes(); exit; } else { waitpid($pid, 0); } my $output = read_warnings($warnings_file); is $output, 'got lock:releasing lock:got lock:releasing lock:got lock:releasing lock'; # shim a delay in before logit() so that it will wait for the child process # to enter the critical section sub shim_logit_delay { no warnings 'redefine'; my $orig_logit = \&Log::Dispatch::FileRotate::logit; *Log::Dispatch::FileRotate::logit = sub { sleep 3; &$orig_logit(@_); }; } sub run_processes { open my $warnfh, '+>', $warnings_file or die "Failed to open warnings file: $!"; $warnfh->autoflush(1); $SIG{__WARN__} = sub { my $msg = shift; # we only want the "got lock" and "exiting" lines if ($msg =~ /got lock/ or $msg =~ /releasing/) { # strip off dates and pid numbers from front of message $msg = substr($msg, 25); $msg =~ s/^-?[0-9]+ //; # save in the warnings file print $warnfh $msg; } }; my $file = Log::Dispatch::FileRotate->new( filename => $tempdir->child('test.log')->stringify, min_level => 'info', DEBUG => 1); my $child1_pid = fork; if ($child1_pid == 0) { $file->log(level => 'info', message => "first_child\n"); } else { sleep 1; my $child2_pid = fork; if ($child2_pid == 0) { $file->log(level => 'info', message => "second_child\n"); } else { waitpid($child1_pid, 0); $file->log(level => 'info', message => "parent\n"); } } delete $SIG{__WARN__}; close $warnfh; } sub read_warnings { my $file = shift; local $/ = undef; open my $fh, '<', $file; my $content = <$fh>; $content =~ s/[\r\n]+$//s; $content =~ s/[\r\n]+/:/sg; return $content; }