better reporting
[gitmo/MooseX-Daemonize.git] / lib / MooseX / Daemonize.pm
1 package MooseX::Daemonize;
2 use strict;    # because Kwalitee is pedantic
3 use Moose::Role;
4
5 our $VERSION = 0.01;
6 use Carp;
7 use Proc::Daemon;
8
9 use File::Flock;
10 use File::Slurp;
11
12 with qw(MooseX::Getopt);
13
14 has progname => (
15     isa      => 'Str',
16     is       => 'ro',
17     lazy     => 1,
18     required => 1,
19     default  => sub {
20         ( my $name = lc $_[0]->meta->name ) =~ s/::/_/g;
21         return $name;
22     },
23 );
24
25 has pidbase => (
26     isa => 'Str',
27     is  => 'ro',
28
29     #    required => 1,
30     lazy    => 1,
31     default => sub { return '/var/run' },
32 );
33
34 has pidfile => (
35     isa      => 'Str',
36     is       => 'ro',
37     lazy     => 1,
38     required => 1,
39     default  => sub {
40         die 'Cannot write to ' . $_[0]->pidbase unless -w $_[0]->pidbase;
41         $_[0]->pidbase . '/' . $_[0]->progname . '.pid';
42     },
43 );
44
45 has foreground => (
46     metaclass   => 'Getopt',
47     cmd_aliases => ['f'],
48     isa         => 'Bool',
49     is          => 'ro',
50     default     => sub { 0 },
51 );
52
53 sub check {
54     my ($self) = @_;
55     if ( my $pid = $self->get_pid ) {
56         my $prog = $self->progname;
57         if ( CORE::kill 0 => $pid ) {
58             croak "$prog already running ($pid).";
59         }
60         carp "$prog not running but found pid ($pid)."
61           . "Perhaps the pid file (@{ [$self->pidfile] }) is stale?";
62         return 1;
63     }
64     return 0;
65 }
66
67 sub daemonize {
68     my ($self) = @_;
69     Proc::Daemon::Init;
70 }
71
72 sub start {
73     my ($self) = @_;
74     return if $self->check;
75
76     $self->daemonize unless $self->foreground;
77
78     # Avoid 'stdin reopened for output' warning with newer perls
79     open( NULL, '/dev/null' );
80     <NULL> if (0);
81
82     $self->save_pid;
83     $self->setup_signals;
84     return $$;
85 }
86
87 sub save_pid {
88     my ($self) = @_;
89     my $pidfile = $self->pidfile;
90     lock( $pidfile, undef, 'nonblocking' )
91       or croak "Could not lock PID file $pidfile: $!";
92     write_file( $pidfile, "$$\n" );
93     unlock($pidfile);
94     return;
95 }
96
97 sub remove_pid {
98     my ($self) = @_;
99     my $pidfile = $self->pidfile;
100     lock( $pidfile, undef, 'nonblocking' )
101       or croak "Could not lock PID file $pidfile: $!";
102     unlink($pidfile);
103     unlock($pidfile);
104     return;
105 }
106
107 sub get_pid {
108     my ($self) = @_;
109     my $pidfile = $self->pidfile;
110     return unless -e $pidfile;
111     chomp( my $pid = read_file($pidfile) );
112     return $pid;
113 }
114
115 sub stop {
116     my ( $self, %args ) = @_;
117     my $pid = $self->get_pid;
118     $self->kill($pid) unless $self->foreground();
119     $self->remove_pid;
120     return 1 if $args{no_exit};
121     exit;
122 }
123
124 sub restart {
125     my ($self) = @_;
126     $self->stop( noexit => 1 );
127     $self->start();
128 }
129
130 sub setup_signals {
131     my ($self) = @_;
132     $SIG{INT} = sub { $self->handle_sigint; };
133     $SIG{HUP} = sub { $self->handle_sighup };
134 }
135
136 sub handle_sigint { $_[0]->stop; }
137 sub handle_sighup { $_[0]->restart; }
138
139 sub kill {
140     my ( $self, $pid ) = @_;
141     return unless $pid;
142     unless ( CORE::kill 0 => $pid ) {
143
144         # warn "$pid already appears dead.";
145         return;
146     }
147
148     if ( $pid eq $$ ) {
149
150         # warn "$pid is us! Can't commit suicied.";
151         return;
152     }
153
154     CORE::kill( 2, $pid );    # Try SIGINT
155     sleep(2) if CORE::kill( 0, $pid );
156
157     unless ( CORE::kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
158         CORE::kill( 15, $pid );                       # try SIGTERM
159         sleep(2) if CORE::kill( 0, $pid );
160     }
161
162     unless ( CORE::kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
163         CORE::kill( 9, $pid );                        # finally try SIGKILL
164         sleep(2) if CORE::kill( 0, $pid );
165     }
166
167     unless ( CORE::kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
168         carp "$pid doesn't seem to want to die.";     # AHH EVIL DEAD!
169     }
170
171     return;
172 }
173
174 1;
175 __END__
176
177 =head1 NAME
178
179 MooseX::Daemonize - provides a Role that daemonizes your Moose based application.
180
181
182 =head1 VERSION
183
184 This document describes MooseX::Daemonize version 0.0.1
185
186
187 =head1 SYNOPSIS
188
189     package FileMaker;
190     use Moose;
191     with qw(MooseX::Daemonize);
192
193     sub create_file {
194         my ( $self, $file ) = @_;
195         open( FILE, ">$file" ) || die;
196         close(FILE);
197     }
198
199     no Moose;
200
201     # then in the main package ... 
202     
203     my $daemon = FileMaker->new();
204     $daemon->start();
205     $daemon->create_file($file);
206     $daemon->stop();
207      
208 =head1 DESCRIPTION
209
210 Often you want to write a persistant daemon that has a pid file, and responds appropriately to Signals. 
211 This module helps provide the basic infrastructure to do that.
212
213 =head1 ATTRIBUTES
214
215 =over
216
217 =item progname Str
218
219 The name of our daemon, defaults to $0
220
221 =item pidbase Str
222
223 The base for our bid, defaults to /var/run/$progname
224
225 =item pidfile Str
226
227 The file we store our PID in, defaults to /var/run/$progname/ 
228
229 =item foreground Bool
230
231 If true, the process won't background. Useful for debugging. This option can be set via Getopt's -f.
232
233 =back
234
235 =head1 METHODS 
236
237 =over
238
239 =item check()
240
241 Check to see if an instance is already running.
242
243 =item start()
244
245 Setup a pidfile, fork, then setup the signal handlers.
246
247 =item stop()
248
249 Stop the process matching the pidfile, and unlinks the pidfile.
250
251 =item restart()
252
253 Litterally 
254
255     $self->stop();
256     $self->start();
257
258 =item daemonize()
259
260 Calls C<Proc::Daemon::Init> to daemonize this process. 
261
262 =item kill($pid)
263
264 Kills the process for $pid. This will try SIGINT, and SIGTERM before falling back to SIGKILL and finally giving up.
265
266 =item setup_signals()
267
268 Setup the signal handlers, by default it only sets up handlers for SIGINT and SIGHUP
269
270 =item handle_sigint()
271
272 Handle a INT signal, by default calls C<$self->stop()>;
273
274 =item handle_sighup()
275
276 Handle a HUP signal. Nothing is done by default.
277
278 =item get_pid
279
280 =item save_pid
281
282 =item remove_pid
283
284 =item meta()
285
286 the C<meta()> method from L<Class::MOP::Class>
287
288 =back
289
290 =head1 DEPENDENCIES
291
292 =for author to fill in:
293     A list of all the other modules that this module relies upon,
294     including any restrictions on versions, and an indication whether
295     the module is part of the standard Perl distribution, part of the
296     module's distribution, or must be installed separately. ]
297
298 Obviously L<Moose>, also L<Carp>, L<Proc::Daemon>, L<File::Flock>, L<File::Slurp>
299
300 =head1 INCOMPATIBILITIES
301
302 =for author to fill in:
303     A list of any modules that this module cannot be used in conjunction
304     with. This may be due to name conflicts in the interface, or
305     competition for system or program resources, or due to internal
306     limitations of Perl (for example, many modules that use source code
307     filters are mutually incompatible).
308
309 None reported.
310
311
312 =head1 BUGS AND LIMITATIONS
313
314 =for author to fill in:
315     A list of known problems with the module, together with some
316     indication Whether they are likely to be fixed in an upcoming
317     release. Also a list of restrictions on the features the module
318     does provide: data types that cannot be handled, performance issues
319     and the circumstances in which they may arise, practical
320     limitations on the size of data sets, special cases that are not
321     (yet) handled, etc.
322
323 No bugs have been reported.
324
325 Please report any bugs or feature requests to
326 C<bug-acme-dahut-call@rt.cpan.org>, or through the web interface at
327 L<http://rt.cpan.org>.
328
329 =head1 SEE ALSO
330
331 L<Proc::Daemon>, L<Daemon::Generic>, L<MooseX::Getopt>
332
333 =head1 AUTHOR
334
335 Chris Prather  C<< <perigrin@cpan.org> >>
336
337
338 =head1 LICENCE AND COPYRIGHT
339
340 Copyright (c) 2007, Chris Prather C<< <perigrin@cpan.org> >>. All rights reserved.
341
342 This module is free software; you can redistribute it and/or
343 modify it under the same terms as Perl itself. See L<perlartistic>.
344
345
346 =head1 DISCLAIMER OF WARRANTY
347
348 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
349 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
350 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
351 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
352 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
353 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
354 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
355 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
356 NECESSARY SERVICING, REPAIR, OR CORRECTION.
357
358 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
359 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
360 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
361 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
362 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
363 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
364 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
365 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
366 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
367 SUCH DAMAGES.