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