File Coverage

blib/lib/Daemon/Daemonize.pm
Criterion Covered Total %
statement 81 115 70.4
branch 35 78 44.8
condition 9 26 34.6
subroutine 15 19 78.9
pod 8 9 88.8
total 148 247 59.9


line stmt bran cond sub pod time code
1             package Daemon::Daemonize;
2             BEGIN {
3 10     10   2200652 $Daemon::Daemonize::VERSION = '0.0052';
4             }
5             # ABSTRACT: An easy-to-use daemon(izing) toolkit
6              
7 10     10   98 use warnings;
  10         26  
  10         312  
8 10     10   56 use strict;
  10         24  
  10         486  
9              
10              
11 10     10   9596 use Sub::Exporter::Util qw/ curry_method /;
  10         163696  
  10         75  
12 10         29 use Sub::Exporter -setup => { exports => [ map { $_ => curry_method } qw/
  90         585  
13             daemonize
14             superclose
15             write_pidfile read_pidfile check_pidfile delete_pidfile
16             does_process_exist can_signal_process check_port
17 10     10   3240 / ] };
  10         25  
18 10     10   20836 use POSIX;
  10         60561  
  10         87  
19 10     10   32811 use Carp;
  10         50  
  10         703  
20 10     10   66 use Path::Class;
  10         17  
  10         12818  
21              
22             sub _fork_or_die {
23 17     17   68 my $self = shift;
24              
25 17         55287 my $pid = fork;
26 17 50       911 confess "Unable to fork" unless defined $pid;
27 17         5225 return $pid;
28             }
29              
30             sub superclose {
31 3     3 0 34 my $self = shift;
32 3   50     1077 my $from = shift || 0;
33              
34 3         139 my $openmax = POSIX::sysconf( &POSIX::_SC_OPEN_MAX );
35 3 50 33     80 $openmax = 64 if ! defined( $openmax ) || $openmax < 0;
36              
37 3 50       26 return unless $from < $openmax;
38              
39 3         3492214 POSIX::close( $_ ) foreach ($from .. $openmax - 1);
40             }
41              
42              
43             sub daemonize {
44 20     20 1 16463 my $self = shift;
45 20         80 my %options = @_;
46              
47             {
48 20 100       36 if ( my $run = delete $options{run} ) {
  20         96  
49              
50 10 100       103 if ( -1 == $self->daemonize( %options, continue => 1 ) ) {
51             # We're the parent, continue on...
52             }
53             else {
54             # We've daemonized... launch into the code we've been given...
55 1         20 $run->();
56 0         0 exit 0;
57             }
58              
59 3         167 return; # Daemonization actually handled in call above... Abort, abort, pull-up!
60             }
61             }
62              
63 10 50       44 my $chdir = exists $options{chdir} ? $options{chdir} : '/';
64 10 50       42 my $close = defined $options{close} ? $options{close} : 1;
65              
66             # Fork once to go into the background
67             {
68 10 100       16 if ( my $pid = $self->_fork_or_die ) {
  10         57  
69 3 50       196 return -1 if $options{continue};
70 0         0 exit 0;
71             }
72             }
73              
74             # Create new session
75 7 50       618 (POSIX::setsid)
76             || confess "Cannot detach from controlling process";
77              
78             # Fork again to ensure that daemon never reacquires a control terminal
79 7 100       261 $self->_fork_or_die && exit 0;
80              
81             # Clear the file creation mask
82 3         668 umask 0;
83              
84 3 50       133 if ( defined $chdir ) {
85 3 50       424 chdir $chdir or confess "Unable to chdir to \"$chdir\": $!";
86             }
87              
88 3 50 33     206 if ( $close eq 1 || $close eq '!std' ) {
89             # Close any open file descriptors
90 3 50       124 $self->superclose( $close eq '!std' ? 3 : 0 );
91             }
92              
93 3   66     105 my $stdout_file = $ENV{DAEMON_DAEMONIZE_STDOUT} || $options{stdout};
94 3   66     91 my $stderr_file = $ENV{DAEMON_DAEMONIZE_STDERR} || $options{stderr};
95              
96 3 50 33     41 if ( $close eq 1 || $close eq 'std' ) {
97             # Re-open STDIN, STDOUT, STDERR to /dev/null
98 3 50       350 open( STDIN, "+>/dev/null" ) or confess "Could not redirect STDIN to /dev/null";
99              
100 3 100       76 unless ( $stdout_file ) {
101 1 50       35 open( STDOUT, "+>&STDIN" ) or confess "Could not redirect STDOUT to /dev/null";
102             }
103              
104 3 100       25 unless ( $stderr_file ) {
105 1 50       17 open( STDERR, "+>&STDIN" ) or confess "Could not redirect STDERR to /dev/null";
106             }
107              
108             # Avoid 'stdin reopened for output' warning (taken from MooseX::Daemonize)
109 3         89 local *_NIL;
110 3         214 open( _NIL, '/dev/null' );
111 3         74 <_NIL> if 0;
112             }
113              
114 3 100       151 if ( $stdout_file ) {
115 2 50       490 open STDOUT, ">>", $stdout_file or confess "Could not redirect STDOUT to $stdout_file : $!";
116             }
117              
118 1 50       16 if ( $stderr_file ) {
119 0 0       0 open STDERR, ">>", $stderr_file or confess "Could not redirect STDERR to $stderr_file : $!";
120             }
121              
122 1         15 return 1;
123             }
124              
125             sub _pidfile($) {
126 7     7   33 my $pidfile = shift;
127 7 50       48 confess "No pidfile given" unless defined $pidfile;
128 7 50       84 return Path::Class::File->new( ref $pidfile eq 'ARRAY' ? @$pidfile : "$pidfile" );
129             }
130              
131              
132             sub read_pidfile {
133 3     3 1 7 my $self = shift;
134 3         22 my $pidfile = _pidfile shift;
135              
136 3 50       325 return unless -s $pidfile;
137 0 0 0     0 return unless -f $pidfile && -r $pidfile;
138 0         0 return scalar $pidfile->slurp( chomp => 1 );
139             }
140              
141              
142             sub check_pidfile {
143 3     3 1 3007884 my $self = shift;
144 3         39 my $pidfile = _pidfile shift;
145              
146 3         1226 my $pid = $self->read_pidfile( $pidfile );
147 3 50       441 return 0 unless $pid;
148 0 0       0 return 0 unless $self->does_process_exist( $pid );
149 0         0 return $pid;
150             }
151              
152              
153             sub write_pidfile {
154 1     1 1 67 my $self = shift;
155 1         12 my $pidfile = _pidfile shift;
156 1   33     551 my $pid = shift || $$;
157              
158 1         83 my $fh = $pidfile->openw;
159 0           $fh->print( $pid . "\n" );
160 0           $fh->close;
161             }
162              
163              
164             sub delete_pidfile {
165 0     0 1   my $self = shift;
166 0           my $pidfile = _pidfile shift;
167              
168 0           $pidfile->remove;
169             }
170              
171              
172             sub does_process_exist {
173 0     0 1   my $self = shift;
174 0           my $pid = shift;
175              
176 0 0         croak "No pid given to check" unless $pid;
177              
178 0 0         return 1 if kill 0, $pid;
179 0           my $errno = $!;
180              
181 0 0         if ( eval { require Errno } ) {
  0            
182 0 0 0       return 1 if exists &Errno::EPERM && $errno == &Errno::EPERM;
183             }
184              
185             # So $errno == ESRCH, or we don't have Errno.pm, ... just going to assume non-existent
186 0           return 0;
187             }
188              
189              
190             sub can_signal_process {
191 0     0 1   my $self = shift;
192 0           my $pid = shift;
193              
194 0 0         croak "No pid given to check" unless $pid;
195              
196 0 0         return kill 0, $pid ? 1 : 0;
197             # So $! is ESRCH or EPERM or something else, so we can't signal/control it
198             }
199              
200              
201             sub check_port {
202 0     0 1   require IO::Socket::INET;
203 0           my $self = shift;
204 0           my $port = shift;
205              
206 0 0         croak "No port given to check" unless $port;
207              
208 0           my $socket = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => $port, Proto => 'tcp' );
209 0 0         if ( $socket ) {
210 0           $socket->close;
211 0           return 1;
212             }
213 0           return 0;
214             }
215              
216              
217             1;
218              
219             __END__
220             =pod
221              
222             =head1 NAME
223              
224             Daemon::Daemonize - An easy-to-use daemon(izing) toolkit
225              
226             =head1 VERSION
227              
228             version 0.0052
229              
230             =head1 SYNOPSIS
231              
232             use Daemon::Daemonize qw/ :all /
233              
234             daemonize( %options, run => sub {
235              
236             # Daemon code in here...
237              
238             } )
239              
240             # Do some non-daemon stuff here...
241              
242             You can also use it in the traditional way, daemonizing the current process:
243              
244             daemonize( %options )
245              
246             # Daemon code in here...
247              
248             and use it to check up on your daemon:
249              
250             # In your daemon
251              
252             use Daemon::Daemonize qw/ :all /
253              
254             write_pidfile( $pidfile )
255             $SIG{INT} = sub { delete_pidfile( $pidfile ) }
256              
257             ... Elsewhere ...
258              
259             use Daemon::Daemonize qw/ :all /
260              
261             # Return the pid from $pidfile if it contains a pid AND
262             # the process is running (even if you don't own it), 0 otherwise
263             my $pid = check_pidfile( $pidfile )
264              
265             # Return the pid from $pidfile, or undef if the
266             # file doesn't exist, is unreadable, etc.
267             # This will return the pid regardless of if the process is running
268             my $pid = read_pidfile( $pidfile )
269              
270             =head1 DESCRIPTION
271              
272             Daemon::Daemonize is a toolkit for daemonizing processes and checking up on them. It takes inspiration from L<http://www.clapper.org/software/daemonize/>, L<MooseX::Daemon>, L<Net::Server::Daemon>
273              
274             =head2 A note about the C<close> option
275              
276             If you're having trouble with IPC in a daemon, try closing only STD* instead of everything:
277              
278             daemonize( ..., close => std, ... )
279              
280             This is a workaround for a problem with using C<Net::Server> and C<IPC::Open3> in a daemonized process
281              
282             =head1 USAGE
283              
284             You can use the following functions in two ways, by either importing them:
285              
286             use Daemon::Daemonize qw/ daemonize /
287              
288             daemonize( ... )
289              
290             or calling them as a class method:
291              
292             use Daemon::Daemonize
293              
294             Daemon::Daemonize->daemonize
295              
296             =head2 daemonize( %options )
297              
298             Daemonize the current process, according to C<%options>:
299              
300             chdir <dir> Change to <dir> when daemonizing. Pass undef for *no* chdir.
301             Default is '/' (to prevent a umount conflict)
302              
303             close <option> Automatically close opened files when daemonizing:
304              
305             1 Close STDIN, STDOUT, STDERR (usually redirected
306             from/to /dev/null). In addition, close any other
307             opened files (up to POSIX::_SC_OPEN_MAX)
308              
309             0 Don't close anything
310              
311             std Only close STD{IN,OUT,ERR} (as in 1)
312              
313             Default is 1 (close everything)
314              
315             stdout <file> Open up STDOUT of the process to <file>. This will override any
316             closing of STDOUT
317              
318             stderr <file> Open up STDERR of the process to <file>. This will override any
319             closing of STDERR
320              
321             run <code> After daemonizing, run the given code and then exit
322              
323             =head2 read_pidfile( $pidfile )
324              
325             Return the pid from $pidfile. Return undef if the file doesn't exist, is unreadable, etc.
326             This will return the pid regardless of if the process is running
327              
328             For an alternative, see C<check_pidfile>
329              
330             =head2 check_pidfile( $pidfile )
331              
332             Return the pid from $pidfile if it contains a pid AND the process is running (even if you don't own it), and 0 otherwise
333              
334             This method will always return a number
335              
336             =head2 write_pidfile( $pidfile, [ $pid ] )
337              
338             Write the given pid to $pidfile, creating/overwriting any existing file. The second
339             argument is optional, and will default to $$ (the current process number)
340              
341             =head2 delete_pidfile( $pidfile )
342              
343             Unconditionally delete (unlink) $pidfile
344              
345             =head2 does_process_exist( $pid )
346              
347             Using C<kill>, attempts to determine if $pid exists (is running).
348              
349             If you don't own $pid, this method will still return true (by examining C<errno> for EPERM).
350              
351             For an alternative, see C<can_signal_process>
352              
353             =head2 can_signal_process( $pid )
354              
355             Using C<kill>, attempts to determine if $pid exists (is running) and is owned (signable) by the user.
356              
357             =head2 check_port( $port )
358              
359             Returns true if $port on the localhost is accepting connections.
360              
361             =head1 SEE ALSO
362              
363             L<MooseX::Daemonize>
364              
365             L<Proc::Daemon>
366              
367             L<Net::Server::Daemonize>
368              
369             =head1 AUTHOR
370              
371             Robert Krimen <robertkrimen@gmail.com>
372              
373             =head1 COPYRIGHT AND LICENSE
374              
375             This software is copyright (c) 2010 by Robert Krimen.
376              
377             This is free software; you can redistribute it and/or modify it under
378             the same terms as the Perl 5 programming language system itself.
379              
380             =cut
381