package RWDE::Runnable; use strict; use warnings; use Error qw(:try); use Getopt::Std; use POSIX qw(:sys_wait_h setsid ceil); use RWDE::DB::DbRegistry; use RWDE::Exceptions; use base qw(RWDE::Logging); sub Start { my ($self, $params) = @_; # Process command line options: # -d turn on debugging (remains in foreground) my %opt = (); getopts('d:s:m:n:', \%opt); RWDE::Logger->set_debug() if exists($opt{d}); my $runnable = $self->new(); $SIG{INT} = sub { $runnable->shutdown() }; $SIG{TERM} = sub { $runnable->shutdown() }; $SIG{'USR1'} = sub { $self->toggle_debug(); }; $runnable->setup(\%opt); $self->daemonize() unless $self->is_debug; $runnable->start(); return (); } sub setup { my ($self, $params) = @_; #give subclasses a chance to setup return (); } sub start { my ($self, $params) = @_; throw RWDE::DevelException({ info => 'start has to be overriden, no work to be done in the abstract clas' }); return (); } sub shutdown { my ($self, $params) = @_; $self->syslog_msg('info', 'Closing...'); try { my $registry = RWDE::DB::DbRegistry->get_instance(); $registry->cleanup(); } catch Error with { my $ex = shift; $self->syslog_msg('info', 'Closing...' . $ex); }; exit(0); } # daemonize: From perlipc man page, fork into background and redirect input and output to dev/null sub daemonize { chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; # parent exits... setsid or die "Can't start a new session: $!"; open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; return; } 1;