From: Stevan Little Date: Sun, 11 Jul 2010 02:34:10 +0000 (-0400) Subject: 0.11 release X-Git-Tag: 0.15~8 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMooseX-Daemonize.git;a=commitdiff_plain;h=2ecc2ccba1b854569f9b5792a72489afec1d17aa 0.11 release --- diff --git a/Changes b/Changes index 42b27b3..e3817f7 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,14 @@ Revision history for MooseX-Daemonize +0.11 Sat. July 10, 2010 + * MooseX::Daemonize::Core + - make the options to daemonize() + into proper attributes but still + retained back-compat (Thanks to Magnus Erixzon) + - adjusted docs and tests + + - removed the pod.t and pod-coverage.t tests + 0.10 Sat. April 17, 2010 - updated copyrights - removed the POE test because it was causing diff --git a/lib/MooseX/Daemonize.pm b/lib/MooseX/Daemonize.pm index c7be66a..e13be00 100644 --- a/lib/MooseX/Daemonize.pm +++ b/lib/MooseX/Daemonize.pm @@ -3,7 +3,7 @@ use strict; # because Kwalitee is pedantic use Moose::Role; use MooseX::Types::Path::Class; -our $VERSION = "0.10"; +our $VERSION = '0.11'; with 'MooseX::Daemonize::WithPidFile', 'MooseX::Getopt'; @@ -368,6 +368,23 @@ The file we store our PID in, defaults to C<$pidbase/$progname.pid> If true, the process won't background. Useful for debugging. This option can be set via Getopt's -f. +=item I + +If true, the process will not perform the typical double-fork, which is extra +added protection from your process accidentally aquiring a controlling terminal. +More information can be found by Googling "double fork daemonize". + +=item I + +If true, the process will not clean up zombie processes. +Normally you don't want this. + +=item I + +If true, the objects open filehandles will not be closed when daemonized. +Normally you don't want this. + + =item I If true, the process is the backgrounded daemon process, if false it is the diff --git a/lib/MooseX/Daemonize/Core.pm b/lib/MooseX/Daemonize/Core.pm index 3d3f1a9..7c4cbdb 100644 --- a/lib/MooseX/Daemonize/Core.pm +++ b/lib/MooseX/Daemonize/Core.pm @@ -3,7 +3,7 @@ use strict; # cause Perl::Critic errors are annoying use MooseX::Getopt; # to load the NoGetopt metaclass use Moose::Role; -our $VERSION = '0.10'; +our $VERSION = '0.11'; use POSIX (); @@ -18,11 +18,43 @@ has is_daemon => ( default => sub { 0 }, ); +has ignore_zombies => ( + metaclass => 'Getopt', + isa => 'Bool', + is => 'rw', + default => sub { 0 }, +); + +has no_double_fork => ( + metaclass => 'Getopt', + isa => 'Bool', + is => 'rw', + default => sub { 0 }, +); + +has dont_close_all_files => ( + metaclass => 'Getopt', + isa => 'Bool', + is => 'rw', + default => sub { 0 }, +); + +sub _get_options { + my ($self, %options) = @_; + # backwards compability.. old code might be calling daemon_fork/_detach with options + foreach my $opt (qw( ignore_zombies no_double_fork dont_close_all_files )) { + $self->$opt( $options{ $opt } ) if ( defined $options{ $opt } ); + } +} + + sub daemon_fork { my ($self, %options) = @_; + $self->_get_options( %options ); + $SIG{CHLD} = 'IGNORE' - if $options{ignore_zombies}; + if $self->ignore_zombies;; if (my $pid = fork) { return $pid; @@ -38,12 +70,13 @@ sub daemon_detach { return unless $self->is_daemon; # return if parent ... + $self->_get_options( %options ); # now we are in the daemon ... (POSIX::setsid) # set session id || confess "Cannot detach from controlling process"; - unless ($options{no_double_fork}) { + unless ( $self->no_double_fork ) { $SIG{'HUP'} = 'IGNORE'; fork && exit; } @@ -51,7 +84,7 @@ sub daemon_detach { chdir '/'; # change to root directory umask 0; # clear the file creation mask - unless ($options{dont_close_all_files}) { + unless ( $self->dont_close_all_files ) { # get the max numnber of possible file descriptors my $openmax = POSIX::sysconf( &POSIX::_SC_OPEN_MAX ); $openmax = 64 if !defined($openmax) || $openmax < 0; @@ -153,38 +186,54 @@ responsibility (see some of the other roles in this distro for that). This attribute is used to signal if we are within the daemon process or not. +=item I rw, isa => Bool)> + +Setting this attribute to true will cause this method to not perform the +typical double-fork, which is extra added protection from your process +accidentally aquiring a controlling terminal. More information can be +found above, and by Googling "double fork daemonize". + +If you the double-fork behavior off, you might want to enable the +I. + +=item I rw, isa => Bool)> + +Setting this attribute to a true value will result in setting the C<$SIG{CHLD}> +handler to C. This tells perl to clean up zombie processes. By +default, and for the most part you don't I it, only when you turn off +the double fork behavior (with the I attribute) +do you sometimes want this behavior. + +=item I rw, isa => Bool)> + +Setting this attribute to true will cause it to skip closing all the +filehandles. This is useful if you are opening things like sockets +and such in the pre-fork. + =back =head1 METHODS =over -=item B +=item B This forks off the child process to be daemonized. Just as with the built in fork, it returns the child pid to the parent process, 0 to the child process. It will also set the is_daemon flag appropriately. -The C<%options> available for this function are: - -=over 4 - -=item I - -Setting this key to a true value will result in setting the C<$SIG{CHLD}> -handler to C. This tells perl to clean up zombie processes. By -default, and for the most part you don't I it, only when you turn off -the double fork behavior (with the I option) in C -do you sometimes want this behavior. - -=back +The C<%options> argument remains for backwards compatability, but +it is suggested that you use the attributes listed above instead. -=item B +=item B This detaches the new child process from the terminal by doing the following things. +The C<%options> argument remains for backwards compatability, but +it is suggested that you use the attributes listed above instead. + =over 4 =item Becomes a session leader @@ -205,7 +254,8 @@ directory then simply change it later in your daemons code. =item Closes all open file descriptors. -See below for information on how to change this part of the process. +See the I attribute for information on how to +change this part of the process. =item Reopen STDERR, STDOUT & STDIN to /dev/null @@ -214,39 +264,17 @@ and MX_DAEMON_STDOUT environment variables. It will look for a filename in either of these variables and redirect STDOUT and/or STDERR to those files. This is useful for debugging and/or testing purposes. -=back - -The C<%options> available for this function are: - -=over 4 - -=item I - -Setting this option to true will cause this method to not perform the -typical double-fork, which is extra added protection from your process -accidentally aquiring a controlling terminal. More information can be -found above, and by Googling "double fork daemonize". - -If you the double-fork behavior off, you might want to enable the -I behavior in the C method. - -=item I - -Setting this option to true will cause it to skip closing all the -filehandles, this is useful if you are opening things like sockets -and such in the pre-fork. - -=back - B If called from within the parent process (the is_daemon flag is set to false), this method will simply return and do nothing. -=item B +=item B + +This will simply call C followed by C. -This will simply call C followed by C, it will -pass any C<%options> onto both methods. +The C<%options> argument remains for backwards compatability, but +it is suggested that you use the attributes listed above instead. =item meta() @@ -286,7 +314,7 @@ written enough so I decided to reproduce it here. terminal. That said, you don't always want this to be the behavior, so you are -free to specify otherwise using the C<%options>. +free to specify otherwise using the I attribute. =item Note about zombies @@ -295,7 +323,7 @@ by the time you have double forked your daemon process is then owned by the init process. However, sometimes the double-fork is more than you really need, and you want to keep your daemon processes a little closer to you. In this case you have to watch out for zombies, you can avoid then -by just setting the C option (see above). +by just setting the I attribute (see above). =back diff --git a/lib/MooseX/Daemonize/Pid.pm b/lib/MooseX/Daemonize/Pid.pm index 2cbf754..dbf8cf7 100644 --- a/lib/MooseX/Daemonize/Pid.pm +++ b/lib/MooseX/Daemonize/Pid.pm @@ -2,7 +2,7 @@ package MooseX::Daemonize::Pid; use strict; # because Kwalitee is pedantic use Moose; use Moose::Util::TypeConstraints; -our $VERSION = '0.10'; +our $VERSION = '0.11'; coerce 'MooseX::Daemonize::Pid' => from 'Int' diff --git a/lib/MooseX/Daemonize/Pid/File.pm b/lib/MooseX/Daemonize/Pid/File.pm index 03311a3..e214c92 100644 --- a/lib/MooseX/Daemonize/Pid/File.pm +++ b/lib/MooseX/Daemonize/Pid/File.pm @@ -3,7 +3,7 @@ use strict; # because Kwalitee is pedantic use Moose; use Moose::Util::TypeConstraints; -our $VERSION = '0.10'; +our $VERSION = '0.11'; use MooseX::Types::Path::Class; use MooseX::Getopt::OptionTypeMap; diff --git a/lib/MooseX/Daemonize/WithPidFile.pm b/lib/MooseX/Daemonize/WithPidFile.pm index e55d38d..b6b71a5 100644 --- a/lib/MooseX/Daemonize/WithPidFile.pm +++ b/lib/MooseX/Daemonize/WithPidFile.pm @@ -2,7 +2,7 @@ package MooseX::Daemonize::WithPidFile; use strict; # cause Perl::Critic errors are annoying use MooseX::Getopt; # to load the Getopt metaclass use Moose::Role; -our $VERSION = '0.10'; +our $VERSION = '0.11'; use MooseX::Daemonize::Pid::File; diff --git a/lib/Test/MooseX/Daemonize.pm b/lib/Test/MooseX/Daemonize.pm index b45245b..4dd29ff 100644 --- a/lib/Test/MooseX/Daemonize.pm +++ b/lib/Test/MooseX/Daemonize.pm @@ -1,7 +1,7 @@ package Test::MooseX::Daemonize; use strict; -our $VERSION = '0.10'; +our $VERSION = '0.11'; our $AUTHORITY = 'cpan:PERIGRIN'; # BEGIN CARGO CULTING diff --git a/t/20.core.t b/t/20.core.t index 0f14dab..e239e80 100644 --- a/t/20.core.t +++ b/t/20.core.t @@ -13,7 +13,7 @@ my $dir = tempdir( CLEANUP => 1 ); BEGIN { use_ok('MooseX::Daemonize::Core'); - use_ok('MooseX::Daemonize::Pid'); + use_ok('MooseX::Daemonize::Pid'); } use constant DEBUG => 0; @@ -24,11 +24,11 @@ $ENV{MX_DAEMON_STDERR} = catfile($dir, 'Err.txt'); { package MyFooDaemon; use Moose; - + with 'MooseX::Daemonize::Core'; - + has 'daemon_pid' => (is => 'rw', isa => 'MooseX::Daemonize::Pid'); - + # capture the PID from the fork around 'daemon_fork' => sub { my $next = shift; @@ -39,27 +39,26 @@ $ENV{MX_DAEMON_STDERR} = catfile($dir, 'Err.txt'); ); } }; - + sub start { - my $self = shift; + my $self = shift; # tell it to ignore zombies ... - $self->daemonize( - ignore_zombies => 1, - no_double_fork => 1, - ); + $self->ignore_zombies( 1 ); + $self->no_double_fork( 1 ); + $self->daemonize; return unless $self->is_daemon; # change to our local dir # so that we can debug easier chdir $dir; # make it easy to find with ps $0 = 'test-app'; - $SIG{INT} = sub { - print "Got INT! Oh Noes!"; + $SIG{INT} = sub { + print "Got INT! Oh Noes!"; exit; - }; + }; while (1) { - print "Hello from $$\n"; - sleep(10); + print "Hello from $$\n"; + sleep(10); } exit; } diff --git a/t/21.core-back-compat.t b/t/21.core-back-compat.t new file mode 100644 index 0000000..d0cd59c --- /dev/null +++ b/t/21.core-back-compat.t @@ -0,0 +1,103 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More 'no_plan'; +use Test::Exception; +use Test::Moose; +use File::Temp qw(tempdir); +use File::Spec::Functions; + +my $dir = tempdir( CLEANUP => 1 ); + +BEGIN { + use_ok('MooseX::Daemonize::Core'); + use_ok('MooseX::Daemonize::Pid'); +} + +use constant DEBUG => 0; + +$ENV{MX_DAEMON_STDOUT} = catfile($dir, 'Out.txt'); +$ENV{MX_DAEMON_STDERR} = catfile($dir, 'Err.txt'); + +{ + package MyFooDaemon; + use Moose; + + with 'MooseX::Daemonize::Core'; + + has 'daemon_pid' => (is => 'rw', isa => 'MooseX::Daemonize::Pid'); + + # capture the PID from the fork + around 'daemon_fork' => sub { + my $next = shift; + my $self = shift; + if (my $pid = $self->$next(@_)) { + $self->daemon_pid( + MooseX::Daemonize::Pid->new(pid => $pid) + ); + } + }; + + sub start { + my $self = shift; + # tell it to ignore zombies ... + $self->daemonize( + ignore_zombies => 1, + no_double_fork => 1, + ); + return unless $self->is_daemon; + # change to our local dir + # so that we can debug easier + chdir $dir; + # make it easy to find with ps + $0 = 'test-app'; + $SIG{INT} = sub { + print "Got INT! Oh Noes!"; + exit; + }; + while (1) { + print "Hello from $$\n"; + sleep(10); + } + exit; + } +} + +my $d = MyFooDaemon->new; +isa_ok($d, 'MyFooDaemon'); +does_ok($d, 'MooseX::Daemonize::Core'); + +lives_ok { + $d->start; +} '... successfully daemonized from (' . $$ . ')'; + +my $p = $d->daemon_pid; +isa_ok($p, 'MooseX::Daemonize::Pid'); + +ok($p->is_running, '... the daemon process is running (' . $p->pid . ')'); + +my $pid = $p->pid; +if (DEBUG) { + diag `ps $pid`; + diag "-------"; + diag `ps -x | grep test-app`; + diag "-------"; + diag "killing $pid"; +} +kill INT => $p->pid; +diag "killed $pid" if DEBUG; +sleep(2); +if (DEBUG) { + diag `ps $pid`; + diag "-------"; + diag `ps -x | grep test-app`; +} + +ok(!$p->is_running, '... the daemon process is no longer running (' . $p->pid . ')'); + +unlink $ENV{MX_DAEMON_STDOUT}; +unlink $ENV{MX_DAEMON_STDERR}; + + diff --git a/t/pod-coverage.t b/t/pod-coverage.t deleted file mode 100644 index 703f91d..0000000 --- a/t/pod-coverage.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -T - -use Test::More; -eval "use Test::Pod::Coverage 1.04"; -plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; -all_pod_coverage_ok(); diff --git a/t/pod.t b/t/pod.t deleted file mode 100644 index 976d7cd..0000000 --- a/t/pod.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -T - -use Test::More; -eval "use Test::Pod 1.14"; -plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; -all_pod_files_ok();