2013-08-01 Ramon Novoa <rnovoa@artica.es>
* lib/PandoraFMS/DataServer.pm, lib/PandoraFMS/SNMPServer.pm, lib/PandoraFMS/Server.pm, lib/PandoraFMS/PluginServer.pm, lib/PandoraFMS/ProducerConsumerServer.pm, lib/PandoraFMS/PredictionServer.pm, lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/NetworkServer.pm, lib/PandoraFMS/WMIServer.pm: Added clean-up code to avoid resource leaks when there is a crash and the server has to auto-restart. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@8611 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
parent
4557e364b9
commit
094defb906
|
@ -1,3 +1,16 @@
|
|||
2013-08-01 Ramon Novoa <rnovoa@artica.es>
|
||||
|
||||
* lib/PandoraFMS/DataServer.pm,
|
||||
lib/PandoraFMS/SNMPServer.pm,
|
||||
lib/PandoraFMS/Server.pm,
|
||||
lib/PandoraFMS/PluginServer.pm,
|
||||
lib/PandoraFMS/ProducerConsumerServer.pm,
|
||||
lib/PandoraFMS/PredictionServer.pm,
|
||||
lib/PandoraFMS/ReconServer.pm,
|
||||
lib/PandoraFMS/NetworkServer.pm,
|
||||
lib/PandoraFMS/WMIServer.pm: Added clean-up code to avoid resource
|
||||
leaks when there is a crash and the server has to auto-restart.
|
||||
|
||||
2013-07-25 Ramon Novoa <rnovoa@artica.es>
|
||||
|
||||
* lib/PandoraFMS/NetworkServer.pm: Fixed some parentheses that prevented
|
||||
|
|
|
@ -46,10 +46,10 @@ our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
|||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my %Agents :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
my $AgentSem :shared = Thread::Semaphore->new (1);
|
||||
my $ModuleSem :shared = Thread::Semaphore->new (1);
|
||||
my $Sem :shared;
|
||||
my $TaskSem :shared;
|
||||
my $AgentSem :shared;
|
||||
my $ModuleSem :shared;
|
||||
|
||||
########################################################################################
|
||||
# Data Server class constructor.
|
||||
|
@ -59,6 +59,15 @@ sub new ($$;$) {
|
|||
|
||||
return undef unless $config->{'dataserver'} == 1;
|
||||
|
||||
# Initialize semaphores and queues
|
||||
@TaskQueue = ();
|
||||
%PendingTasks = ();
|
||||
%Agents = ();
|
||||
$Sem = Thread::Semaphore->new;
|
||||
$TaskSem = Thread::Semaphore->new (0);
|
||||
$AgentSem = Thread::Semaphore->new (1);
|
||||
$ModuleSem = Thread::Semaphore->new (1);
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 0, \&PandoraFMS::DataServer::data_producer, \&PandoraFMS::DataServer::data_consumer, $dbh);
|
||||
|
||||
|
|
|
@ -42,9 +42,8 @@ our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
|||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = new Thread::Semaphore;
|
||||
my $TaskSem :shared = new Thread::Semaphore (0);
|
||||
my $SNMPSem :shared = new Thread::Semaphore (1);
|
||||
my $Sem :shared;
|
||||
my $TaskSem :shared;
|
||||
|
||||
########################################################################################
|
||||
# Network Server class constructor.
|
||||
|
@ -60,6 +59,12 @@ sub new ($$$) {
|
|||
return undef;
|
||||
}
|
||||
|
||||
# Initialize semaphores and queues
|
||||
@TaskQueue = ();
|
||||
%PendingTasks = ();
|
||||
$Sem = Thread::Semaphore->new;
|
||||
$TaskSem = Thread::Semaphore->new (0);
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 1, \&PandoraFMS::NetworkServer::data_producer, \&PandoraFMS::NetworkServer::data_consumer, $dbh);
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
|||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
my $Sem :shared;
|
||||
my $TaskSem :shared;
|
||||
|
||||
########################################################################################
|
||||
# Plugin Server class constructor.
|
||||
|
@ -59,7 +59,13 @@ sub new ($$;$) {
|
|||
print_message ($config, ' [E] ' . $config->{'plugin_exec'} . ' not found. Plugin Server not started.', 1);
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
# Initialize semaphores and queues
|
||||
@TaskQueue = ();
|
||||
%PendingTasks = ();
|
||||
$Sem = Thread::Semaphore->new;
|
||||
$TaskSem = Thread::Semaphore->new (0);
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 4, \&PandoraFMS::PluginServer::data_producer, \&PandoraFMS::PluginServer::data_consumer, $dbh);
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
|||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
my $Sem :shared;
|
||||
my $TaskSem :shared;
|
||||
|
||||
########################################################################
|
||||
# Prediction Server class constructor.
|
||||
|
@ -55,10 +55,16 @@ sub new ($$;$) {
|
|||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'predictionserver'} == 1;
|
||||
|
||||
|
||||
# Initialize semaphores and queues
|
||||
@TaskQueue = ();
|
||||
%PendingTasks = ();
|
||||
$Sem = Thread::Semaphore->new;
|
||||
$TaskSem = Thread::Semaphore->new (0);
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 5, \&PandoraFMS::PredictionServer::data_producer, \&PandoraFMS::PredictionServer::data_consumer, $dbh);
|
||||
|
||||
|
||||
bless $self, $class;
|
||||
|
||||
return $self;
|
||||
|
|
|
@ -31,9 +31,12 @@ use PandoraFMS::DB;
|
|||
use PandoraFMS::Core;
|
||||
use PandoraFMS::Server;
|
||||
|
||||
# inherits from PandoraFMS::Server
|
||||
# Inherits from PandoraFMS::Server
|
||||
our @ISA = qw(PandoraFMS::Server);
|
||||
|
||||
# Tells the producer and consumers to keep running
|
||||
my $RUN :shared;
|
||||
|
||||
########################################################################################
|
||||
# ProducerConsumerServer class constructor.
|
||||
########################################################################################
|
||||
|
@ -48,6 +51,9 @@ sub new ($$$$$;$) {
|
|||
$self->{'_producer'} = $producer;
|
||||
$self->{'_consumer'} = $consumer;
|
||||
|
||||
# Run!
|
||||
$RUN = 1;
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
@ -101,14 +107,15 @@ sub run ($$$$$) {
|
|||
sub data_producer ($$$$$) {
|
||||
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
|
||||
my $pa_config = $self->getConfig ();
|
||||
my $dbh;
|
||||
|
||||
eval {
|
||||
# Connect to the DB
|
||||
my $dbh = db_connect ($pa_config->{'dbengine'}, $pa_config->{'dbname'}, $pa_config->{'dbhost'}, $pa_config->{'dbport'},
|
||||
$dbh = db_connect ($pa_config->{'dbengine'}, $pa_config->{'dbname'}, $pa_config->{'dbhost'}, $pa_config->{'dbport'},
|
||||
$pa_config->{'dbuser'}, $pa_config->{'dbpass'});
|
||||
$self->setDBH ($dbh);
|
||||
|
||||
while (1) {
|
||||
while ($RUN == 1) {
|
||||
|
||||
# Get pending tasks
|
||||
my @tasks = &{$self->{'_producer'}}($self);
|
||||
|
@ -140,6 +147,9 @@ sub data_producer ($$$$$) {
|
|||
if ($@) {
|
||||
$self->setErrStr ($@);
|
||||
}
|
||||
|
||||
$task_sem->up($self->getNumThreads ());
|
||||
db_disconnect ($dbh);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
@ -149,13 +159,14 @@ sub data_consumer ($$$$$) {
|
|||
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
my $dbh;
|
||||
eval {
|
||||
# Connect to the DB
|
||||
my $dbh = db_connect ($pa_config->{'dbengine'}, $pa_config->{'dbname'}, $pa_config->{'dbhost'}, $pa_config->{'dbport'},
|
||||
$dbh = db_connect ($pa_config->{'dbengine'}, $pa_config->{'dbname'}, $pa_config->{'dbhost'}, $pa_config->{'dbport'},
|
||||
$pa_config->{'dbuser'}, $pa_config->{'dbpass'});
|
||||
$self->setDBH ($dbh);
|
||||
|
||||
while (1) {
|
||||
while ($RUN == 1) {
|
||||
|
||||
# Wait for data
|
||||
$task_sem->down;
|
||||
|
@ -164,6 +175,9 @@ sub data_consumer ($$$$$) {
|
|||
my $task = shift (@{$task_queue});
|
||||
$sem->up;
|
||||
|
||||
# The consumer was waiting for data when the producer exited
|
||||
last if ($RUN == 0);
|
||||
|
||||
# Execute task
|
||||
&{$self->{'_consumer'}}($self, $task);
|
||||
|
||||
|
@ -179,6 +193,17 @@ sub data_consumer ($$$$$) {
|
|||
if ($@) {
|
||||
$self->setErrStr ($@);
|
||||
}
|
||||
|
||||
db_disconnect ($dbh);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Clean-up when the server is destroyed.
|
||||
###############################################################################
|
||||
sub DESTROY {
|
||||
my $self = shift;
|
||||
|
||||
$RUN = 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -45,8 +45,8 @@ our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
|||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
my $Sem :shared;
|
||||
my $TaskSem :shared;
|
||||
|
||||
########################################################################################
|
||||
# Recon Server class constructor.
|
||||
|
@ -61,6 +61,12 @@ sub new ($$$$$$) {
|
|||
print_message ($config, ' [E] ' . $config->{'nmap'} . " needed by Pandora FMS Recon Server not found.", 1);
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Initialize semaphores and queues
|
||||
@TaskQueue = ();
|
||||
%PendingTasks = ();
|
||||
$Sem = Thread::Semaphore->new;
|
||||
$TaskSem = Thread::Semaphore->new (0);
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 3, \&PandoraFMS::ReconServer::data_producer, \&PandoraFMS::ReconServer::data_consumer, $dbh);
|
||||
|
|
|
@ -38,6 +38,9 @@ use PandoraFMS::Server;
|
|||
# Inherits from PandoraFMS::Server
|
||||
our @ISA = qw(PandoraFMS::Server);
|
||||
|
||||
# Tells the server to keep running
|
||||
my $RUN :shared;
|
||||
|
||||
########################################################################################
|
||||
# SNMP Server class constructor.
|
||||
########################################################################################
|
||||
|
@ -50,13 +53,16 @@ sub new ($$;$) {
|
|||
if (start_snmptrapd ($config) != 0) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 2, $dbh);
|
||||
|
||||
# Save the path of snmptrapd
|
||||
$self->{'snmp_trapd'} = $config->{'snmp_trapd'};
|
||||
|
||||
|
||||
# Run!
|
||||
$RUN = 1;
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
@ -79,9 +85,10 @@ sub pandora_snmptrapd {
|
|||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
my $dbh;
|
||||
eval {
|
||||
# Connect to the DB
|
||||
my $dbh = db_connect ($pa_config->{'dbengine'}, $pa_config->{'dbname'}, $pa_config->{'dbhost'},
|
||||
$dbh = db_connect ($pa_config->{'dbengine'}, $pa_config->{'dbname'}, $pa_config->{'dbhost'},
|
||||
$pa_config->{'dbport'}, $pa_config->{'dbuser'}, $pa_config->{'dbpass'});
|
||||
$self->setDBH ($dbh);
|
||||
|
||||
|
@ -111,7 +118,7 @@ sub pandora_snmptrapd {
|
|||
readline SNMPLOGFILE for (1..$last_line);
|
||||
|
||||
# Main loop
|
||||
while (1) {
|
||||
while ($RUN == 1) {
|
||||
while (my $line = <SNMPLOGFILE>) {
|
||||
$last_line++;
|
||||
$last_size = (stat ($log_file))[7];
|
||||
|
@ -189,6 +196,8 @@ sub pandora_snmptrapd {
|
|||
if ($@) {
|
||||
$self->setErrStr ($@);
|
||||
}
|
||||
|
||||
db_disconnect ($dbh);
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
|
@ -287,5 +296,14 @@ sub start_snmptrapd ($) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Clean-up when the server is destroyed.
|
||||
###############################################################################
|
||||
sub DESTROY {
|
||||
my $self = shift;
|
||||
|
||||
$RUN = 0;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
|
|
@ -29,7 +29,7 @@ use lib '/usr/lib/perl5';
|
|||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
|
||||
# defined in PandoraFMS::Core.pm
|
||||
# Defined in PandoraFMS::Core.pm
|
||||
our @ServerSuffixes;
|
||||
|
||||
########################################################################################
|
||||
|
@ -51,13 +51,7 @@ sub new ($$$;$) {
|
|||
# Share variables that may be set from different threads
|
||||
share ($self->{'_queue_size'});
|
||||
share ($self->{'_errstr'});
|
||||
|
||||
# Thread kill signal handler
|
||||
#$SIG{'KILL'} = sub {
|
||||
# threads->exit() if threads->can('exit');
|
||||
# exit();
|
||||
#};
|
||||
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
@ -290,17 +284,12 @@ sub stop ($) {
|
|||
0, $self->{'_server_type'}, 0, 0);
|
||||
};
|
||||
|
||||
# Kill server threads
|
||||
# Detach server threads
|
||||
foreach my $tid (@{$self->{'_threads'}}) {
|
||||
my $thr = threads->object($tid);
|
||||
next unless defined ($thr);
|
||||
|
||||
# A kill method might not be available
|
||||
#if ($thr->can('kill')) {
|
||||
# $thr->kill('KILL')->detach();
|
||||
#} else {
|
||||
$thr->detach();
|
||||
#}
|
||||
$thr->detach();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
|||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
my $Sem :shared;
|
||||
my $TaskSem :shared;
|
||||
|
||||
########################################################################################
|
||||
# NetworkServer class constructor.
|
||||
|
@ -58,7 +58,13 @@ sub new ($$;$) {
|
|||
print_message ($config, ' [E] ' . $config->{'wmi_client'} . " not found. Pandora FMS WMI Server needs a DCOM/WMI client.", 1);
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
# Initialize semaphores and queues
|
||||
@TaskQueue = ();
|
||||
%PendingTasks = ();
|
||||
$Sem = Thread::Semaphore->new;
|
||||
$TaskSem = Thread::Semaphore->new (0);
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 6, \&PandoraFMS::WMIServer::data_producer, \&PandoraFMS::WMIServer::data_consumer, $dbh);
|
||||
|
||||
|
@ -138,7 +144,7 @@ sub data_consumer ($$) {
|
|||
|
||||
# Build command to execute
|
||||
my $wmi_command = '';
|
||||
if ($module->{'plugin_user'}) {
|
||||
if (defined ($module->{'plugin_pass'}) && $module->{'plugin_pass'} ne "") {
|
||||
$wmi_command = $pa_config->{'wmi_client'} . ' -U "' . $module->{'plugin_user'} . '"%"' . $module->{'plugin_pass'} . '"';
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Reference in New Issue