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