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