document is_daemon
[gitmo/MooseX-Daemonize.git] / lib / MooseX / Daemonize.pm
CommitLineData
a4952679 1package MooseX::Daemonize;
a392fa53 2use strict; # because Kwalitee is pedantic
a4952679 3use Moose::Role;
4
cbff8e52 5our $VERSION = 0.02;
a4952679 6use Carp;
7use Proc::Daemon;
a392fa53 8
fa2b72a4 9use File::Pid;
10use Moose::Util::TypeConstraints;
a4952679 11
12with qw(MooseX::Getopt);
13
14has progname => (
a392fa53 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 },
a4952679 23);
24
24a6a660 25has basedir => (
cbff8e52 26 isa => 'Str',
27 is => 'ro',
28 required => 1,
29 lazy => 1,
30 default => sub { return '/' },
24a6a660 31);
32
a4952679 33has pidbase => (
cbff8e52 34 isa => 'Str',
35 is => 'ro',
36 lazy => 1,
37 required => 1,
38 default => sub { return '/var/run' },
a4952679 39);
40
fa2b72a4 41subtype 'Pidfile' => as 'Object' => where { $_->isa('File::Pid') };
cbff8e52 42
43coerce 'Pidfile' => from 'Str' => via { File::Pid->new( { file => $_, } ); };
fa2b72a4 44
a4952679 45has pidfile => (
cbff8e52 46 isa => 'Pidfile',
47 is => 'rw',
48 lazy => 1,
49 required => 1,
50 coerce => 1,
51 predicate => 'has_pidfile',
52 default => sub {
fa2b72a4 53 my $file = $_[0]->pidbase . '/' . $_[0]->progname . '.pid';
e7a196e7 54 die "Cannot write to $file" unless (-e $file ? -w $file : -w $_[0]->pidbase);
fa2b72a4 55 File::Pid->new( { file => $file } );
56 },
57 handles => {
58 check => 'running',
59 save_pid => 'write',
60 remove_pid => 'remove',
61 get_pid => 'pid',
cbff8e52 62 _pidfile => 'file',
3543c999 63 },
a4952679 64);
65
66has foreground => (
cbff8e52 67 metaclass => 'MooseX::Getopt::Meta::Attribute',
68 cmd_aliases => 'f',
a4952679 69 isa => 'Bool',
70 is => 'ro',
71 default => sub { 0 },
72);
73
cbff8e52 74has is_daemon => (
75 isa => 'Bool',
76 is => 'rw',
77 default => sub { 0 },
78);
79
a392fa53 80sub daemonize {
81 my ($self) = @_;
cbff8e52 82 return if Proc::Daemon::Fork;
a392fa53 83 Proc::Daemon::Init;
cbff8e52 84 $self->is_daemon(1);
a392fa53 85}
86
a4952679 87sub start {
88 my ($self) = @_;
cbff8e52 89 confess "instance already running" if $self->check;
a4952679 90 $self->daemonize unless $self->foreground;
91
cbff8e52 92 return unless $self->is_daemon;
93
94 $self->pidfile->pid($$);
95
3543c999 96 # Avoid 'stdin reopened for output' warning with newer perls
0585edbb 97 ## no critic
3543c999 98 open( NULL, '/dev/null' );
99 <NULL> if (0);
0585edbb 100 ## use critic
fa2b72a4 101
24a6a660 102 # Change to basedir
103 chdir $self->basedir;
fa2b72a4 104
3543c999 105 $self->save_pid;
106 $self->setup_signals;
107 return $$;
108}
109
3543c999 110sub stop {
111 my ( $self, %args ) = @_;
112 my $pid = $self->get_pid;
cecbee2d 113 $self->_kill($pid) unless $self->foreground();
3543c999 114 $self->remove_pid;
115 return 1 if $args{no_exit};
116 exit;
117}
118
a4952679 119sub restart {
120 my ($self) = @_;
7ada91b8 121 $self->stop( no_exit => 1 );
a4952679 122 $self->start();
123}
124
a4952679 125sub setup_signals {
3543c999 126 my ($self) = @_;
127 $SIG{INT} = sub { $self->handle_sigint; };
128 $SIG{HUP} = sub { $self->handle_sighup };
a4952679 129}
130
2361a590 131sub handle_sigint { $_[0]->stop; }
132sub handle_sighup { $_[0]->restart; }
a4952679 133
cecbee2d 134sub _kill {
135 confess "_kill isn't public" unless caller eq __PACKAGE__;
a4952679 136 my ( $self, $pid ) = @_;
2361a590 137 return unless $pid;
3543c999 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.";
a4952679 147 return;
148 }
149
3543c999 150 CORE::kill( 2, $pid ); # Try SIGINT
2361a590 151 sleep(2) if CORE::kill( 0, $pid );
a4952679 152
3543c999 153 unless ( CORE::kill 0 => $pid or $!{EPERM} ) { # IF it is still running
154 CORE::kill( 15, $pid ); # try SIGTERM
2361a590 155 sleep(2) if CORE::kill( 0, $pid );
a4952679 156 }
157
3543c999 158 unless ( CORE::kill 0 => $pid or $!{EPERM} ) { # IF it is still running
159 CORE::kill( 9, $pid ); # finally try SIGKILL
7ada91b8 160 sleep(3) if CORE::kill( 0, $pid );
a4952679 161 }
162
3543c999 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!
a4952679 165 }
166
167 return;
168}
169
1701;
171__END__
172
a4952679 173=head1 NAME
174
175MooseX::Daemonize - provides a Role that daemonizes your Moose based application.
176
177
178=head1 VERSION
179
180This 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
206Often you want to write a persistant daemon that has a pid file, and responds appropriately to Signals.
207This module helps provide the basic infrastructure to do that.
208
209=head1 ATTRIBUTES
210
211=over
212
213=item progname Str
214
cbff8e52 215The name of our daemon, defaults to $self->meta->name =~ s/::/_/;
a4952679 216
217=item pidbase Str
218
219The base for our bid, defaults to /var/run/$progname
220
221=item pidfile Str
222
223The file we store our PID in, defaults to /var/run/$progname/
224
225=item foreground Bool
226
227If true, the process won't background. Useful for debugging. This option can be set via Getopt's -f.
228
e7a196e7 229=item is_daemon Bool
230
231If true, the process is the backgrounded process. This is useful for example in an after 'start' => sub { } block
232
a4952679 233=back
234
235=head1 METHODS
236
237=over
238
239=item check()
240
241Check to see if an instance is already running.
242
243=item start()
244
245Setup a pidfile, fork, then setup the signal handlers.
246
247=item stop()
248
249Stop the process matching the pidfile, and unlinks the pidfile.
250
251=item restart()
252
253Litterally
254
255 $self->stop();
256 $self->start();
257
258=item daemonize()
259
260Calls C<Proc::Daemon::Init> to daemonize this process.
261
262=item kill($pid)
263
264Kills 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
268Setup the signal handlers, by default it only sets up handlers for SIGINT and SIGHUP
269
270=item handle_sigint()
271
cecbee2d 272Handle a INT signal, by default calls C<$self->stop()>
a4952679 273
274=item handle_sighup()
275
cecbee2d 276Handle a HUP signal. By default calls C<$self->restart()>
a4952679 277
3543c999 278=item get_pid
279
cecbee2d 280Lookup the pid from our pidfile.
281
3543c999 282=item save_pid
283
cecbee2d 284Save the current pid in our pidfile
285
3543c999 286=item remove_pid
287
cecbee2d 288Delete our pidfile
289
a4952679 290=item meta()
291
cecbee2d 292The C<meta()> method from L<Class::MOP::Class>
a4952679 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
fa2b72a4 304Obviously L<Moose>, also L<Carp>, L<Proc::Daemon>, L<File::Pid>
a4952679 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
315None 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
329No bugs have been reported.
330
331Please report any bugs or feature requests to
332C<bug-acme-dahut-call@rt.cpan.org>, or through the web interface at
333L<http://rt.cpan.org>.
334
335=head1 SEE ALSO
336
337L<Proc::Daemon>, L<Daemon::Generic>, L<MooseX::Getopt>
338
339=head1 AUTHOR
340
341Chris Prather C<< <perigrin@cpan.org> >>
342
7ada91b8 343=head1 THANKS
344
345Mike Boyko, Matt S. Trout, Stevan Little, Brandon Black, and the #moose denzians
a4952679 346
347=head1 LICENCE AND COPYRIGHT
348
349Copyright (c) 2007, Chris Prather C<< <perigrin@cpan.org> >>. All rights reserved.
350
351This module is free software; you can redistribute it and/or
352modify it under the same terms as Perl itself. See L<perlartistic>.
353
354
355=head1 DISCLAIMER OF WARRANTY
356
357BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
358FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
359OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
360PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
361EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
362WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
363ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
364YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
365NECESSARY SERVICING, REPAIR, OR CORRECTION.
366
367IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
368WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
369REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
370LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
371OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
372THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
373RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
374FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
375SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
376SUCH DAMAGES.