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