File Coverage

blib/lib/Log/Dispatch/FileRotate/Flock.pm
Criterion Covered Total %
statement 33 44 75.0
branch 8 18 44.4
condition 0 3 0.0
subroutine 7 7 100.0
pod 2 2 100.0
total 50 74 67.5


line stmt bran cond sub pod time code
1             #
2             # This file is part of Log-Dispatch-FileRotate
3             #
4             # This software is copyright (c) 2005 by Mark Pfeiffer.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9              
10             package Log::Dispatch::FileRotate::Flock;
11             $Log::Dispatch::FileRotate::Flock::VERSION = '1.38';
12             # ABSTRACT: File Locking Functions for L<Log::Dispatch::FileRotate>
13              
14 8     8   55 use strict;
  8         18  
  8         242  
15 8     8   42 use warnings;
  8         15  
  8         235  
16              
17 8     8   39 use base 'Exporter';
  8         15  
  8         721  
18              
19 8     8   51 use Fcntl ':flock';
  8         18  
  8         1747  
20              
21             our @EXPORT_OK = qw(safe_flock flopen);
22              
23              
24             sub safe_flock {
25 452     452 1 840 my ($fh, $flags) = @_;
26              
27 452         703 while (1) {
28 452 50       4698 unless (flock $fh, $flags) {
29             # retry if we were interrupted or we are in non-blocking and the file is locked
30 0 0 0 7   0 next if $!{EAGAIN} or $!{EWOULDBLOCK};
  7         3401  
  7         9411  
  7         59  
31              
32 0         0 return 0;
33             }
34             else {
35 452         2122 return 1;
36             }
37             }
38             }
39              
40              
41             sub flopen {
42 6     6 1 13 my $path = shift;
43              
44 6         13 my $flags = LOCK_EX; my $fh;
  6         10  
45              
46 6         13 while (1) {
47 6 50       866 unless (open $fh, '>>', $path) {
48 0         0 return;
49             }
50              
51 6 50       40 unless (safe_flock($fh, $flags)) {
52 0         0 return;
53             }
54              
55 6         99 my @path_stat = stat $path;
56 6 50       36 unless (@path_stat) {
57             # file disappeared fron under our feet
58 0         0 close $fh;
59 0         0 next;
60             }
61              
62 6         59 my @fh_stat = stat $fh;
63 6 50       32 unless (@fh_stat) {
64             # This should never happen
65 0         0 return;
66             }
67              
68 6 50       55 unless ($^O =~ /^MSWin/) {
69             # stat on a filehandle and path return different "dev" and "rdev"
70             # fields on windows
71 6 50       26 if ($path_stat[0] != $fh_stat[0]) {
72             # file was changed under our feet. try again;
73 0         0 close $fh;
74 0         0 next;
75             }
76             }
77              
78             # check that inode are the same for the path and fh
79 6 50       20 if ($path_stat[1] != $fh_stat[1])
80             {
81             # file was changed under our feet. try again;
82 0         0 close $fh;
83 0         0 next;
84             }
85              
86 6         52 return ($fh, $fh_stat[1]);
87             }
88             }
89              
90             1;
91              
92             __END__
93              
94             =pod
95              
96             =encoding UTF-8
97              
98             =head1 NAME
99              
100             Log::Dispatch::FileRotate::Flock - File Locking Functions for L<Log::Dispatch::FileRotate>
101              
102             =head1 VERSION
103              
104             version 1.38
105              
106             =head1 SYNOPSIS
107              
108             Internal Use Only!
109              
110             =head2 DESCRIPTION
111              
112             Internal Use Only!
113              
114             =head1 METHODS
115              
116             =head2 safe_flock($filehandle, $flags): boolean
117              
118             This is a wrapper around C<flock()> that handles things such as interruption of
119             the call by a signal automatically.
120              
121             =head2 flopen($path): ($filehandle, $inode)
122              
123             This function is similar to BSD's C<flopen()> function. It opens a file,
124             obtiains an exclusive lock on it using C<flock()>, and handles a bunch of race
125             conditions that can happen. It returns the opened filehandle and the inode of
126             the file on success, nothing on failure.
127              
128             =head1 SOURCE
129              
130             The development version is on github at L<https://https://github.com/mschout/perl-log-dispatch-filerotate>
131             and may be cloned from L<git://https://github.com/mschout/perl-log-dispatch-filerotate.git>
132              
133             =head1 BUGS
134              
135             Please report any bugs or feature requests on the bugtracker website
136             L<https://github.com/mschout/perl-log-dispatch-filerotate/issues>
137              
138             When submitting a bug or request, please include a test-file or a
139             patch to an existing test-file that illustrates the bug or desired
140             feature.
141              
142             =head1 AUTHOR
143              
144             Michael Schout <mschout@cpan.org>
145              
146             =head1 COPYRIGHT AND LICENSE
147              
148             This software is copyright (c) 2005 by Mark Pfeiffer.
149              
150             This is free software; you can redistribute it and/or modify it under
151             the same terms as the Perl 5 programming language system itself.
152              
153             =cut