File Coverage

blib/lib/PID/File.pm
Criterion Covered Total %
statement 104 108 96.3
branch 27 32 84.3
condition 4 4 100.0
subroutine 24 27 88.8
pod 7 7 100.0
total 166 178 93.2


line stmt bran cond sub pod time code
1             package PID::File;
2              
3 18     18   913393 use 5.006;
  18         74  
  18         817  
4              
5 18     18   105 use strict;
  18         37  
  18         685  
6 18     18   96 use warnings;
  18         50  
  18         642  
7              
8 18     18   101 use File::Basename qw(fileparse);
  18         29  
  18         2826  
9 18     18   16236 use FindBin qw($Bin);
  18         21934  
  18         2217  
10 18     18   121 use Scalar::Util qw(weaken);
  18         34  
  18         2392  
11              
12 18     18   10306 use PID::File::Guard;
  18         65  
  18         617  
13              
14 18     18   276 use constant DEFAULT_SLEEP => 1;
  18         30  
  18         1233  
15 18     18   89 use constant DEFAULT_RETRIES => 0;
  18         25  
  18         45557  
16              
17             =head1 NAME
18              
19             PID::File - PID files that guard against exceptions.
20              
21             =head1 VERSION
22              
23             Version 0.32
24              
25             =cut
26              
27             our $VERSION = '0.32';
28             $VERSION = eval $VERSION;
29              
30             =head1 SYNOPSIS
31              
32             Create PID files.
33              
34             use PID::File;
35              
36             my $pid_file = PID::File->new;
37              
38             exit if $pid_file->running;
39              
40             if ( $pid_file->create )
41             {
42             $pid_file->guard;
43              
44             # do something
45              
46             $pid_file->remove;
47             }
48              
49             Using the built-in retry mechanism...
50              
51             if ( ! $pid_file->create( retries => 10, sleep => 5 ) )
52             {
53             die "Could not create pid file after 10 attempts";
54             }
55              
56             # do something
57              
58             $pid_file->remove;
59              
60             =head1 DESCRIPTION
61              
62             Creating a pid file, or lock file, should be such a simple process.
63              
64             See L for a more complete solution for creating daemons (and pid files).
65              
66             After creating a pid file, if an exception is thrown (and the C<$pid_file> goes out of scope) the pid file would normally remain in place.
67              
68             If you call C on the pid object after creation, it will remove the pid file automatically when it goes out of scope. More on this later.
69              
70             =head1 Methods
71              
72             =head2 Class Methods
73              
74             =head3 new
75              
76             my $pid_file = PID::File->new;
77              
78             =cut
79              
80             sub new
81             {
82 17     17 1 359 my ( $class, %args ) = @_;
83              
84             my $self = { file => $args{ file },
85 2     2   132 guard => sub { return },
86 1     1   2 guard_temp => sub { return },
87 17         193 };
88              
89 17         63 bless( $self, $class );
90              
91 17         70 return $self;
92             }
93              
94             =head2 Instance Methods
95              
96             =head3 file
97              
98             The filename for the pid file.
99              
100             $pid_file->file( '/tmp/myapp.pid' );
101              
102             If you specify a relative path, it will be relative to where your scripts runs.
103              
104             By default it will use the script name and append C<.pid> to it.
105              
106             =cut
107              
108             sub file
109             {
110 121     121 1 3215 my ( $self, $arg ) = @_;
111              
112 121 100       428 $self->{ file } = $arg if $arg;
113              
114 121 100       395 if ( ! defined $self->{ file } )
115             {
116 13         476 my @filename = fileparse( $0 );
117 13         55 $self->{ file } = $Bin . '/';
118 13         45 $self->{ file } .= shift @filename;
119 13         41 $self->{ file } .= '.pid';
120             }
121              
122             # relative paths are made absolute, to the script dir
123              
124 121 100       538 if ( $self->{ file } !~ m:^/: )
125             {
126 3         16 $self->{ file } = $Bin . '/' . $self->{ file };
127             }
128              
129 121         5445 return $self->{ file };
130             }
131              
132             =head3 create
133              
134             Attempt to create a new pid file.
135              
136             if ( $pid_file->create )
137              
138             Returns true or false.
139              
140             If the file already exists, no action will be taken and it will return false.
141              
142             If you supply the C parameter, it will retry that many times, sleeping for C seconds (1 by default) between retries.
143              
144             if ( ! $pid_file->create( retries => 5, sleep => 2 ) )
145             {
146             die "Could not create pid file";
147             }
148              
149             As a shortcut, you can also C the pid file by passing the C boolean as a parameter.
150              
151             $pid_file->create( guard => 1 );
152              
153             See below for more details on the guard mechanism.
154              
155             =cut
156              
157             sub create
158             {
159 19     19 1 21927 my ( $self, %args ) = @_;
160              
161 19   100     256 my $sleep = $args{ sleep } || DEFAULT_SLEEP;
162 19   100     255 my $retries = $args{ retries } || DEFAULT_RETRIES;
163              
164 19         86 my $temp = $self->file . '.' . $$;
165              
166 19 50       4553 open( my $fh, '>', $temp ) or return 0;
167              
168 19     0   142 $self->{ guard_temp } = sub { unlink $temp };
  0         0  
169              
170 19         338 print $fh $$;
171 19         1391 close $fh;
172              
173 19         47 my $attempts = 0;
174              
175 19         87 while ( $attempts <= $retries )
176             {
177 21 100       100 if ( link( $temp, $self->file ) )
178             {
179 18         3478 unlink $temp;
180              
181 18     15   109 $self->{ guard_temp } = sub { return };
  15         28  
182              
183 18         126 $self->pid( $$ );
184 18         68 $self->_created( 1 );
185              
186 18 100       65 $self->guard if $args{ guard };
187              
188 18         215 return 1;
189             }
190              
191 3 100       28 last if $attempts == $retries;
192              
193 2         7 $attempts ++;
194              
195 2         2000855 sleep $sleep;
196             }
197              
198 1         92982 unlink $temp;
199 1     0   19 $self->{ guard_temp } = sub { return };
  0         0  
200              
201 1         37 return 0;
202             }
203              
204             sub _created
205             {
206 60     60   90 my $self = shift;
207 60 100       182 $self->{ _created } = $_[0] if @_;
208 60         157 return $self->{ _created };
209             }
210              
211             =head3 pid
212              
213             $pid_file->pid
214              
215             Stores the pid from the pid file, if one exists. Could be undefined.
216              
217             =cut
218              
219             sub pid
220             {
221 48     48 1 79 my $self = shift;
222 48 100       193 $self->{ pid } = $_[0] if @_;
223 48         105 return $self->{ pid };
224             }
225              
226             =head3 running
227              
228             if ( $pid_file->running )
229              
230             Returns true or false to indicate whether the pid in the current pid file is running.
231              
232             =cut
233              
234             sub running
235             {
236 9     9 1 955 my $self = shift;
237              
238 9         26 $self->pid( undef );
239              
240 9 100       47 open( my $fh, $self->file ) or return 0;
241 3         8 my $pid = do { local $/; <$fh> };
  3         12  
  3         68  
242 3 50       43 close $fh or return 1;
243              
244 3 50       56 if ( kill 0, $pid )
245             {
246 3         9 $self->pid( $pid );
247 3         69 return 1;
248             }
249              
250 0         0 return 0;
251             }
252              
253             =head3 remove
254              
255             Removes the pid file.
256              
257             $pid_file->remove;
258              
259             You can only remove a pid file that was created by the same process.
260              
261             =cut
262              
263             sub remove
264             {
265 16     16 1 135 my ( $self, %args ) = @_;
266              
267 16 50       57 return $self if ! $self->_created;
268              
269 16         49 unlink $self->file;
270 16         92 $self->pid( undef );
271 16         66 $self->_created( 0 );
272 16     10   92 $self->{ guard } = sub { return };
  10         860  
273              
274 16         464 return $self;
275             }
276              
277             =head3 guard
278              
279             This deals with scenarios where your script may throw an exception before you can remove the lock file yourself.
280              
281             When called in void context, this configures the C<$pid_file> object to call C automatically when it goes out of scope.
282              
283             if ( $pid_file->create )
284             {
285             $pid_file->guard;
286              
287             die;
288             }
289              
290             When called in either scalar or list context, it will return a single token.
291              
292             When that B goes out of scope, C is called automatically.
293              
294             This gives more control on when to automatically remove the pid file.
295              
296             if ( $pid_file->create )
297             {
298             my $guard = $pid_file->guard;
299             }
300              
301             # remove() called automatically, even though $pid_file is still in scope
302              
303             Note, that if you call C yourself, the guard configuration will be reset, to save trying to remove the
304             file again when the C<$pid_file> object finally goes out of scope naturally.
305              
306             You can only guard a pid file that was created by the same process.
307              
308             =cut
309              
310             sub guard
311             {
312 10     10 1 1058 my ( $self, %args ) = shift;
313              
314 10 50       34 return if ! $self->_created;
315              
316 10 100       47 if ( ! defined wantarray )
317             {
318 6     4   5841 $self->{ guard } = sub { 1 };
  4         27  
319 6         40 return $self;
320             }
321             else
322             {
323 4     4   187 my $guard = PID::File::Guard->new( sub { $self->remove } );
  4         15  
324 4     0   18 $self->{ guard } = sub{ return };
  0         0  
325 4         25 return $guard;
326             }
327             }
328              
329             sub DESTROY
330             {
331 16     16   5870 my $self = shift;
332              
333 16         86 $self->{ guard_temp }->();
334              
335 16 100       48 $self->remove if $self->{ guard }->();
336             }
337              
338             =head1 AUTHOR
339              
340             Rob Brown, C<< >>
341              
342             =head1 BUGS
343              
344             Please report any bugs or feature requests to C, or through
345             the web interface at L. I will be notified, and then you will
346             automatically be notified of progress on your bug as I make changes.
347              
348             =head1 SUPPORT
349              
350             You can find documentation for this module with the perldoc command.
351              
352             perldoc PID::File
353              
354             You can also look for information at:
355              
356             =over 4
357              
358             =item * RT: CPAN's request tracker (report bugs here)
359              
360             L
361              
362             =item * AnnoCPAN: Annotated CPAN documentation
363              
364             L
365              
366             =item * CPAN Ratings
367              
368             L
369              
370             =item * Search CPAN
371              
372             L
373              
374             =back
375              
376             =head1 SEE ALSO
377              
378             L
379              
380             L
381              
382             =head1 LICENSE AND COPYRIGHT
383              
384             Copyright 2012 Rob Brown.
385              
386             This program is free software; you can redistribute it and/or modify it
387             under the terms of either: the GNU General Public License as published
388             by the Free Software Foundation; or the Artistic License.
389              
390             See http://dev.perl.org/licenses/ for more information.
391              
392             =cut
393              
394             1; # End of PID::File
395