change the kill sleeps to sleep just a little bit longer cause sleep(1) wasn't catchi...
[gitmo/MooseX-Daemonize.git] / lib / MooseX / Daemonize.pm
index 2a92e61..d2cfa86 100644 (file)
@@ -1,27 +1,34 @@
 package MooseX::Daemonize;
-use strict; # because Kwalitee is pedantic
+use strict;    # because Kwalitee is pedantic
 use Moose::Role;
 
 our $VERSION = 0.01;
 use Carp;
 use Proc::Daemon;
+
 use File::Flock;
 use File::Slurp;
 
 with qw(MooseX::Getopt);
 
 has progname => (
-    isa     => 'Str',
-    is      => 'ro',
-    default => sub { lc $_[0]->meta->name },
-);
-
-has pidbase => (
     isa      => 'Str',
     is       => 'ro',
     lazy     => 1,
     required => 1,
-    default  => sub { return '/var/run' },
+    default  => sub {
+        ( my $name = lc $_[0]->meta->name ) =~ s/::/_/g;
+        return $name;
+    },
+);
+
+has pidbase => (
+    isa => 'Str',
+    is  => 'ro',
+
+    #    required => 1,
+    lazy    => 1,
+    default => sub { return '/var/run' },
 );
 
 has pidfile => (
@@ -29,7 +36,10 @@ has pidfile => (
     is       => 'ro',
     lazy     => 1,
     required => 1,
-    default  => sub { $_[0]->pidbase .'/'. $_[0]->progname . '.pid' },
+    default  => sub {
+        die 'Cannot write to ' . $_[0]->pidbase unless -w $_[0]->pidbase;
+        $_[0]->pidbase . '/' . $_[0]->progname . '.pid';
+    },
 );
 
 has foreground => (
@@ -42,92 +52,119 @@ has foreground => (
 
 sub check {
     my ($self) = @_;
-    my $pidfile = $self->pidfile;
-    if ( -e $pidfile ) {
+    if ( my $pid = $self->get_pid ) {
         my $prog = $self->progname;
-        chomp( my $pid = read_file($pidfile) );
-        unless ( kill 0 => $pid or $!{EPERM} ) {
-            carp "$prog already running ($pid).";
-        }
-        else {
-            carp "$prog not running but $pidfile exists. Perhaps it is stale?";
+        if ( CORE::kill 0 => $pid ) {
+            croak "$prog already running ($pid).";
         }
+        carp "$prog not running but $pid exists. Perhaps it is stale?";
         return 1;
     }
     return 0;
 }
 
+sub daemonize {
+    my ($self) = @_;
+    Proc::Daemon::Init;
+}
+
 sub start {
     my ($self) = @_;
     return if $self->check;
 
     $self->daemonize unless $self->foreground;
 
+    # Avoid 'stdin reopened for output' warning with newer perls
+    open( NULL, '/dev/null' );
+    <NULL> if (0);
+
+    $self->save_pid;
+    $self->setup_signals;
+    return $$;
+}
+
+sub save_pid {
+    my ($self) = @_;
     my $pidfile = $self->pidfile;
     lock( $pidfile, undef, 'nonblocking' )
       or croak "Could not lock PID file $pidfile: $!";
     write_file( $pidfile, "$$\n" );
-
-    $self->setup_signals;
+    unlock($pidfile);
     return;
 }
 
-sub stop {
+sub remove_pid {
     my ($self) = @_;
     my $pidfile = $self->pidfile;
-    unless ( -e $pidfile ) {
-        croak $self->progname . 'is not currently running.';
-    }
     lock( $pidfile, undef, 'nonblocking' )
       or croak "Could not lock PID file $pidfile: $!";
-    chomp( my $pid = read_file($pidfile) );
-    $self->kill($pid);
     unlink($pidfile);
+    unlock($pidfile);
     return;
 }
 
-sub restart {
+sub get_pid {
     my ($self) = @_;
-    $self->stop();
-    $self->start();
+    my $pidfile = $self->pidfile;
+    return unless -e $pidfile;
+    chomp( my $pid = read_file($pidfile) );
+    return $pid;
 }
 
-sub daemonize {
+sub stop {
+    my ( $self, %args ) = @_;
+    my $pid = $self->get_pid;
+    $self->kill($pid) unless $self->foreground();
+    $self->remove_pid;
+    return 1 if $args{no_exit};
+    exit;
+}
+
+sub restart {
     my ($self) = @_;
-    Proc::Daemon::Init;
+    $self->stop( noexit => 1 );
+    $self->start();
 }
 
 sub setup_signals {
-    my $self = @_;
-    $SIG{INT} = sub { $_[0]->handle_sigint; };
-    $SIG{HUP} = sub { $_[0]->handle_sighup };
+    my ($self) = @_;
+    $SIG{INT} = sub { $self->handle_sigint; };
+    $SIG{HUP} = sub { $self->handle_sighup };
 }
 
 sub handle_sigint { $_[0]->stop; }
-sub handle_sighup { return; }
+sub handle_sighup { $_[0]->restart; }
 
 sub kill {
     my ( $self, $pid ) = @_;
-    unless ( kill 0 => $pid or $!{EPERM} ) {
-        carp "$pid appears dead.";
+    return unless $pid;
+    unless ( CORE::kill 0 => $pid ) {
+
+        # warn "$pid already appears dead.";
         return;
     }
 
-    kill( 2, $pid );    # Try SIGINT
-    sleep(1) if kill( 0, $pid );
+    if ( $pid eq $$ ) {
 
-    unless ( kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
-        kill( 15, $pid );                       # try SIGTERM
-        sleep(1) if kill( 0, $pid );
+        # warn "$pid is us! Can't commit suicied.";
+        return;
     }
 
-    unless ( kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
-        kill( 9, $pid );                        # finally try SIGKILL
-        sleep(1) if kill( 0, $pid );
+    CORE::kill( 2, $pid );    # Try SIGINT
+    sleep(2) if CORE::kill( 0, $pid );
+
+    unless ( CORE::kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
+        CORE::kill( 15, $pid );                       # try SIGTERM
+        sleep(2) if CORE::kill( 0, $pid );
     }
 
-    unless ( kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
-        carp "$pid doesn't seem to want to die.";    # AHH EVIL DEAD!
+    unless ( CORE::kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
+        CORE::kill( 9, $pid );                        # finally try SIGKILL
+        sleep(2) if CORE::kill( 0, $pid );
+    }
+
+    unless ( CORE::kill 0 => $pid or $!{EPERM} ) {    # IF it is still running
+        carp "$pid doesn't seem to want to die.";     # AHH EVIL DEAD!
     }
 
     return;
@@ -136,7 +173,6 @@ sub kill {
 1;
 __END__
 
-
 =head1 NAME
 
 MooseX::Daemonize - provides a Role that daemonizes your Moose based application.
@@ -238,6 +274,12 @@ Handle a INT signal, by default calls C<$self->stop()>;
 
 Handle a HUP signal. Nothing is done by default.
 
+=item get_pid
+
+=item save_pid
+
+=item remove_pid
+
 =item meta()
 
 the C<meta()> method from L<Class::MOP::Class>