1 package MooseX::Daemonize;
2 use strict; # because Kwalitee is pedantic
4 use MooseX::Types::Path::Class;
5 use File::Path qw(make_path);
7 with 'MooseX::Daemonize::WithPidFile',
14 metaclass => 'Getopt',
20 ( my $name = lc $_[0]->meta->name ) =~ s/::/_/g;
23 documentation => 'the name of the daemon',
27 metaclass => 'Getopt',
28 isa => 'Path::Class::Dir',
33 default => sub { Path::Class::Dir->new('', 'var', 'run') },
34 documentation => 'the base for our pid (default: /var/run)',
38 metaclass => 'Getopt',
39 isa => 'Path::Class::Dir',
44 default => sub { Path::Class::Dir->new('/') },
45 documentation => 'the directory to chdir to (default: /)',
49 metaclass => 'Getopt',
54 documentation => 'if true, the process won\'t background',
58 metaclass => 'Getopt',
62 documentation => 'number of seconds to wait for the process to stop, before trying harder to kill it (default: 2 s)',
65 # internal book-keeping
67 has status_message => (
68 metaclass => 'NoGetopt',
71 clearer => 'clear_status_message',
75 metaclass => 'NoGetopt',
78 clearer => 'clear_exit_code',
83 ## PID file related stuff ...
87 my $file = $self->pidbase . '/' . $self->progname . '.pid';
89 if ( !-d $self->pidbase ) {
90 make_path( $self->pidbase, { error => \my $err } );
92 confess sprintf( "Cannot create pidbase directory '%s': %s",
93 $self->pidbase, @$err );
97 confess "Cannot write to $file" unless (-e $file ? -w $file : -w $self->pidbase);
98 MooseX::Daemonize::Pid::File->new( file => $file );
102 sub check { (shift)->pidfile->is_running }
103 sub save_pid { (shift)->pidfile->write }
104 sub remove_pid { (shift)->pidfile->remove }
105 sub get_pid { (shift)->pidfile->pid }
107 ## signal handling ...
111 $SIG{'INT'} = sub { $self->shutdown };
112 # I can't think of a sane default here really ...
113 # $SIG{'HUP'} = sub { $self->handle_sighup };
118 $self->pidfile->remove if $self->pidfile->pid == $$;
122 ## daemon control methods ...
127 $self->clear_status_message;
128 $self->clear_exit_code;
130 if ($self->pidfile->is_running) {
131 $self->exit_code($self->OK);
132 $self->status_message('Daemon is already running with pid (' . $self->pidfile->pid . ')');
133 return !($self->exit_code);
136 if ($self->foreground) {
140 eval { $self->daemonize };
142 $self->exit_code($self->ERROR);
143 $self->status_message('Start failed : ' . $@);
144 return !($self->exit_code);
148 unless ($self->is_daemon) {
149 $self->exit_code($self->OK);
150 $self->status_message('Start succeeded');
151 return !($self->exit_code);
154 $self->pidfile->pid($$);
157 chdir $self->basedir;
159 $self->pidfile->write;
160 $self->setup_signals;
167 $self->clear_status_message;
168 $self->clear_exit_code;
170 if ($self->pidfile->is_running) {
171 $self->exit_code($self->OK);
172 $self->status_message('Daemon is running with pid (' . $self->pidfile->pid . ')');
175 $self->exit_code($self->ERROR);
176 $self->status_message('Daemon is not running with pid (' . $self->pidfile->pid . ')');
179 return !($self->exit_code);
185 $self->clear_status_message;
186 $self->clear_exit_code;
188 unless ($self->stop) {
189 $self->exit_code($self->ERROR);
190 $self->status_message('Restart (Stop) failed : ' . $@);
193 unless ($self->start) {
194 $self->exit_code($self->ERROR);
195 $self->status_message('Restart (Start) failed : ' . $@);
198 if ($self->exit_code == $self->OK) {
199 $self->exit_code($self->OK);
200 $self->status_message("Restart successful");
203 return !($self->exit_code);
206 # Make _kill *really* private
212 $self->clear_status_message;
213 $self->clear_exit_code;
215 # if the pid is not running
216 # then we don't need to stop
218 if ($self->pidfile->is_running) {
220 # if we are foreground, then
221 # no need to try and kill
223 unless ($self->foreground) {
225 # kill the process ...
226 eval { $self->$_kill($self->pidfile->pid) };
227 # and complain if we can't ...
229 $self->exit_code($self->ERROR);
230 $self->status_message('Stop failed : ' . $@);
232 # or gloat if we succeed ..
234 $self->exit_code($self->OK);
235 $self->status_message('Stop succeeded');
241 # this just returns the OK
242 # exit code for now, but
243 # we should make this overridable
244 $self->exit_code($self->OK);
245 $self->status_message("Not running");
248 # if we are returning to our script
249 # then we actually need the opposite
250 # of what the system/OS expects
251 return !($self->exit_code);
255 my ( $self, $pid ) = @_;
257 unless ( CORE::kill 0 => $pid ) {
258 # warn "$pid already appears dead.";
263 die "$pid is us! Can't commit suicide.";
266 my $timeout = $self->stop_timeout;
268 # kill 0 => $pid returns 0 if the process is dead
269 # $!{EPERM} could also be true if we cant kill it (permission error)
271 # Try SIGINT ... 2s ... SIGTERM ... 2s ... SIGKILL ... 3s ... UNDEAD!
272 my $terminating_signal;
273 for ( [ 2, $timeout ], [15, $timeout], [9, $timeout * 1.5] ) {
274 my ($signal, $timeout) = @$_;
275 $timeout = int $timeout;
277 CORE::kill($signal, $pid);
280 unless(CORE::kill 0 => $pid or $!{EPERM}) {
281 $terminating_signal = $signal;
285 sleep(1) if $timeout;
288 last if $terminating_signal;
291 if($terminating_signal) {
292 if($terminating_signal == 9) {
293 # clean up the pidfile ourselves iff we used -9 and it worked
294 warn "Had to resort to 'kill -9' and it worked, wiping pidfile";
295 eval { $self->pidfile->remove };
297 warn "Could not remove pidfile ("
298 . $self->pidfile->file
305 # IF it is still running
306 Carp::carp "$pid doesn't seem to want to die."; # AHH EVIL DEAD!
316 MooseX::Daemonize - Role for daemonizing your Moose based application
320 The maintainers of this module now recommend using L<Daemon::Control> instead.
327 with qw(MooseX::Daemonize);
329 # ... define your class ....
333 return unless $self->is_daemon;
334 # your daemon code here ...
337 # then in your script ...
339 my $daemon = My::Daemon->new_with_options();
341 my ($command) = @{$daemon->extra_argv}
342 defined $command || die "No command specified";
344 $daemon->start if $command eq 'start';
345 $daemon->status if $command eq 'status';
346 $daemon->restart if $command eq 'restart';
347 $daemon->stop if $command eq 'stop';
349 warn($daemon->status_message);
350 exit($daemon->exit_code);
354 Often you want to write a persistent daemon that has a pid file, and responds
355 appropriately to Signals. This module provides a set of basic roles as an
356 infrastructure to do that.
360 When going into background MooseX::Daemonize closes all open file
361 handles. This may interfere with you logging because it may also close the log
362 file handle you want to write to. To prevent this you can either defer opening
363 the log file until after start. Alternatively, use can use the
364 'dont_close_all_files' option either from the command line or in your .sh
367 Assuming you want to use Log::Log4perl for example you could expand the
368 MooseX::Daemonize example above like this.
372 return unless $self->is_daemon;
373 Log::Log4perl->init(\$log4perl_config);
374 my $logger = Log::Log4perl->get_logger();
375 $logger->info("Daemon started");
376 # your daemon code here ...
382 This list includes attributes brought in from other roles as well
383 we include them here for ease of documentation. All of these attributes
384 are settable though L<MooseX::Getopt>'s command line handling, with the
385 exception of C<is_daemon>.
389 =item I<progname Path::Class::Dir | Str>
391 The name of our daemon, defaults to C<$package_name =~ s/::/_/>;
393 =item I<pidbase Path::Class::Dir | Str>
395 The base for our PID, defaults to C</var/run/>
397 =item I<basedir Path::Class::Dir | Str>
399 The directory we chdir to; defaults to C</>.
401 =item I<pidfile MooseX::Daemonize::Pid::File | Str>
403 The file we store our PID in, defaults to C<$pidbase/$progname.pid>
405 =item I<foreground Bool>
407 If true, the process won't background. Useful for debugging. This option can
408 be set via Getopt's -f.
410 =item I<no_double_fork Bool>
412 If true, the process will not perform the typical double-fork, which is extra
413 added protection from your process accidentally acquiring a controlling terminal.
414 More information can be found by Googling "double fork daemonize".
416 =item I<ignore_zombies Bool>
418 If true, the process will not clean up zombie processes.
419 Normally you don't want this.
421 =item I<dont_close_all_files Bool>
423 If true, the objects open filehandles will not be closed when daemonized.
424 Normally you don't want this.
427 =item I<is_daemon Bool>
429 If true, the process is the backgrounded daemon process, if false it is the
430 parent process. This is useful for example in an C<after 'start' => sub { }>
433 B<NOTE:> This option is explicitly B<not> available through L<MooseX::Getopt>.
435 =item I<stop_timeout>
437 Number of seconds to wait for the process to stop, before trying harder to kill
438 it. Defaults to 2 seconds.
442 These are the internal attributes, which are not available through MooseX::Getopt.
446 =item I<exit_code Int>
448 =item I<status_message Str>
454 =head2 Daemon Control Methods
456 These methods can be used to control the daemon behavior. Every effort
457 has been made to have these methods DWIM (Do What I Mean), so that you
458 can focus on just writing the code for your daemon.
460 Extending these methods is best done with the L<Moose> method modifiers,
461 such as C<before>, C<after> and C<around>.
467 Setup a pidfile, fork, then setup the signal handlers.
471 Stop the process matching the pidfile, and unlinks the pidfile.
487 =head2 Pidfile Handling Methods
491 =item B<init_pidfile>
493 This method will create a L<MooseX::Daemonize::Pid::File> object and tell
494 it to store the PID in the file C<$pidbase/$progname.pid>.
498 This checks to see if the daemon process is currently running by checking
503 Returns the PID of the daemon process.
515 =head2 Signal Handling Methods
519 =item B<setup_signals>
521 Setup the signal handlers, by default it only sets up handlers for SIGINT and
522 SIGHUP. If you wish to add more signals just use the C<after> method modifier
525 =item B<handle_sigint>
527 Handle a INT signal, by default calls C<$self->stop()>
529 =item B<handle_sighup>
531 Handle a HUP signal. By default calls C<$self->restart()>
535 =head2 Exit Code Methods
537 These are overridable constant methods used for setting the exit code.
557 The C<meta()> method from L<Class::MOP::Class>
563 L<Moose>, L<MooseX::Getopt>, L<MooseX::Types::Path::Class> and L<POSIX>
565 =head1 INCOMPATIBILITIES
567 None reported. Although obviously this will not work on Windows.
569 =head1 BUGS AND LIMITATIONS
571 No bugs have been reported.
573 Please report any bugs or feature requests to
574 C<bug-acme-dahut-call@rt.cpan.org>, or through the web interface at
575 L<http://rt.cpan.org>.
579 L<Daemon::Control>, L<Proc::Daemon>, L<Daemon::Generic>
583 Chris Prather C<< <chris@prather.org >>
585 Stevan Little C<< <stevan.little@iinteractive.com> >>
589 Mike Boyko, Matt S. Trout, Stevan Little, Brandon Black, Ash Berlin and the
592 Some bug fixes sponsored by Takkle Inc.
594 =head1 LICENCE AND COPYRIGHT
596 Copyright (c) 2007-2011, Chris Prather C<< <chris@prather.org> >>. Some rights
599 This module is free software; you can redistribute it and/or
600 modify it under the same terms as Perl itself. See L<perlartistic>.
602 =head1 DISCLAIMER OF WARRANTY
604 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
605 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
606 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
607 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
608 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
609 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
610 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
611 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
612 NECESSARY SERVICING, REPAIR, OR CORRECTION.
614 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
615 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
616 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
617 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
618 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
619 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
620 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
621 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
622 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF