File Coverage

blib/lib/PkgForge/PidFile.pm
Criterion Covered Total %
statement 33 67 49.2
branch 0 18 0.0
condition 0 2 0.0
subroutine 11 17 64.7
pod 6 6 100.0
total 50 110 45.4


line stmt bran cond sub pod time code
1             package PkgForge::PidFile; # -*- perl -*-
2 2     2   1454 use strict;
  2         5  
  2         77  
3 2     2   12 use warnings;
  2         4  
  2         99  
4              
5             # $Id: PidFile.pm.in 15149 2010-12-17 09:00:50Z squinney@INF.ED.AC.UK $
6             # $Source:$
7             # $Revision: 15149 $
8             # $HeadURL: https://svn.lcfg.org/svn/source/tags/PkgForge-Server/PkgForge_Server_1_1_10/lib/PkgForge/PidFile.pm.in $
9             # $Date: 2010-12-17 09:00:50 +0000 (Fri, 17 Dec 2010) $
10              
11             our $VERSION = '1.1.10';
12              
13 2     2   11 use English qw( -no_match_vars );
  2         2  
  2         18  
14 2     2   994 use Fcntl qw(:flock O_WRONLY O_EXCL O_CREAT);
  2         3  
  2         293  
15 2     2   11 use File::Spec ();
  2         5  
  2         28  
16 2     2   9 use IO::File ();
  2         4  
  2         44  
17              
18 2     2   11 use Moose;
  2         4  
  2         16  
19 2     2   13271 use Moose::Util::TypeConstraints;
  2         6  
  2         20  
20 2     2   6236 use MooseX::Getopt::OptionTypeMap;
  2         17685  
  2         46  
21 2     2   51 use MooseX::Types::Moose qw(Int Str);
  2         3  
  2         21  
22              
23             coerce 'PkgForge::PidFile',
24             from Str,
25             via { PkgForge::PidFile->new( file => $_ ) };
26              
27             MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
28             'PkgForge::PidFile' => '=s',
29             );
30              
31             has 'file' => (
32             is => 'rw',
33             isa => Str,
34             lazy => 1,
35             predicate => 'has_pidfile',
36             builder => 'init_pidfile',
37             );
38              
39             has 'pid' => (
40             is => 'rw',
41             isa => Int,
42             lazy => 1,
43             predicate => 'has_pid',
44             clearer => 'clear_pid',
45             builder => 'init_pid',
46             );
47              
48             has 'progname' => (
49             is => 'rw',
50             isa => Str,
51             default => sub { return (File::Spec->splitpath( $PROGRAM_NAME ) )[-1] },
52             );
53              
54             has 'basedir' => (
55             is => 'rw',
56             isa => Str,
57             default => sub { File::Spec->tmpdir },
58             );
59              
60             has 'mode' => (
61             is => 'rw',
62             isa => Int,
63             default => sub { oct '0644' },
64             );
65              
66             sub init_pid {
67 0     0 1   my ($self) = @_;
68              
69 0           my $pid;
70 0 0         if ( $self->does_file_exist ) {
71 0           my $file = $self->file;
72              
73 0 0         my $fh = IO::File->new( $file, 'r' )
74             or die "Could not open PID file $file: $OS_ERROR\n";
75 0           chomp( my $contents = $fh->getline );
76 0           $fh->close;
77              
78 0 0         if ( $contents =~ m/^(\d+)/ ) {
79 0           $pid = $1;
80             }
81             else {
82 0           die "Failed to parse contents of PID file $file\n";
83             }
84             }
85              
86 0 0         $pid = $PROCESS_ID if !defined $pid; # Default
87              
88 0           return $pid;
89             }
90              
91             sub init_pidfile {
92 0     0 1   my ($self) = @_;
93              
94 0           my $file = $self->progname . '.pid';
95 0           return File::Spec->catfile( $self->basedir, $file );
96             }
97              
98             sub store {
99 0     0 1   my ($self) = @_;
100              
101 0           my $file = $self->file;
102              
103 0           my $pid = $self->pid;
104              
105 0 0         my $fh = IO::File->new( $file, O_WRONLY|O_EXCL|O_CREAT, $self->mode )
106             or die "Could not open PID file $file: $OS_ERROR\n";
107 0 0         flock( $fh, LOCK_EX|LOCK_NB ) or die "Could not lock: $OS_ERROR\n";
108 0           $fh->print($pid . "\n");
109 0 0         $fh->close or die "Could not close PID file: $OS_ERROR\n";
110              
111 0           return 1;
112             }
113              
114             sub does_file_exist {
115 0     0 1   my ($self) = @_;
116              
117             # Done this way to avoid it returning an undef
118 0   0       return ( -f $self->file || 0 );
119             }
120              
121             sub is_running {
122 0     0 1   my ($self) = @_;
123              
124 0           my $pid = $self->pid;
125              
126 0 0         if ( -d "/proc/$pid" ) {
127 0           return 1;
128             } else {
129 0           return kill 0, $pid;
130             }
131              
132             }
133              
134             sub remove {
135 0     0 1   my ($self) = @_;
136              
137 0 0         if ( $self->does_file_exist ) {
138 0           return unlink $self->file;
139             }
140             else {
141 0           return 1;
142             }
143             }
144              
145 2     2   12222 no Moose;
  2         4  
  2         13  
146             __PACKAGE__->meta->make_immutable;
147              
148             1;
149             __END__
150              
151             =head1 NAME
152              
153             PkgForge::PidFile - A class to provide simple PID file handling
154              
155             =head1 VERSION
156              
157             This documentation refers to PkgForge::PidFile version 1.1.10
158              
159             =head1 SYNOPSIS
160              
161             use PkgForge::PidFile;
162              
163             my $pidfile = PkgForge::PidFile->new();
164              
165             if ( $pidfile->is_running ) {
166             my $pid = $pidfile->pid;
167             die "daemon process ($pid) already running\n";
168             }
169             elsif ( $pidfile->does_file_exist ) {
170             $self->pidfile->remove;
171             }
172              
173             $pidfile->pid($PROCESS_ID);
174             $pidfile->store;
175              
176             =head1 DESCRIPTION
177              
178              
179             =head1 ATTRIBUTES
180              
181             =over
182              
183             =item file
184              
185             A string representing the full path to the file in which the PID is stored.
186              
187             =item pid
188              
189             An integer PID.
190              
191             =item progname
192              
193             The name of the program being run. The default is based on the
194             contents of the C<$0> variable.
195              
196             =item basedir
197              
198             This is the directory into which the PID file will be stored. The
199             default value is that returned by C<File::Spec> C<tmpdir> method. This
200             will only be used when you have not specified a full path for the
201             C<file> attribute.
202              
203             =item mode
204              
205             This is the mode with which a new PID file will be created. The
206             default is C<0644>.
207              
208             =back
209              
210             =head1 SUBROUTINES/METHODS
211              
212             =over
213              
214             =item init_pid
215              
216             If the PID file already exists then the value stored in the file will
217             be returned. Otherwise the value in the C<$$> variable will be
218             returned.
219              
220             =item clear_pid
221              
222             This can be used to clear the value set for the C<pid> attribute. This
223             will force the PID file to be read again, or, if it does not exist,
224             the value to be reset to that in the C<$$> variable.
225              
226             =item init_pidfile
227              
228             This returns the full path to the default location for the PID
229             file. The filename is based on the C<progname> resource with a C<.pid>
230             suffix. It will be in the directory specified in the C<basedir>
231             attribute.
232              
233             =item store
234              
235             This will write the value specified in the C<pid> attribute into the
236             file specified in the C<file> attribute. You can control the mode of
237             the file created via the C<mode> attribute. If another process using
238             this module already has the PID file open for writing then this method
239             will fail immediately.
240              
241             =item does_file_exist
242              
243             Returns true/false to to show whether the file specified in the
244             C<file> attribute actually exists.
245              
246             =item is_running
247              
248             If the PID file exists then this will check if there is a process with
249             this PID actually running and return true/false. The function first
250             looks in the C</proc> directory, if that is not present then it will
251             use the C<kill> function with a signal of zero. If the PID file does
252             not exist then this method returns undef.
253              
254             =item remove
255              
256             If the PID file exists then this will attempt to unlink it and return
257             true/false to indicate success. If the file already does not exist the
258             method just returns true.
259              
260             =back
261              
262             =head1 DEPENDENCIES
263              
264             This module is powered by L<Moose>. It also requires L<MooseX::Getopt>
265             and L< MooseX::Types>.
266              
267             =head1 SEE ALSO
268              
269             =head1 PLATFORMS
270              
271             This is the list of platforms on which we have tested this
272             software. We expect this software to work on any Unix-like platform
273             which is supported by Perl.
274              
275             ScientificLinux5, Fedora13
276              
277             =head1 BUGS AND LIMITATIONS
278              
279             Please report any bugs or problems (or praise!) to bugs@lcfg.org,
280             feedback and patches are also always very welcome.
281              
282             =head1 AUTHOR
283              
284             Stephen Quinney <squinney@inf.ed.ac.uk>
285              
286             =head1 LICENSE AND COPYRIGHT
287              
288             Copyright (C) 201O University of Edinburgh. All rights reserved.
289              
290             This library is free software; you can redistribute it and/or modify
291             it under the terms of the GPL, version 2 or later.
292              
293             =cut