use Config;
use Time::Local;
use Getopt::Long;
-use POSIX;
+use POSIX qw(:sys_wait_h);
+
+my $numchild;
+$MAX_CHILDREN = 10;
$debug = $restart = $kill = 0;
sub listen_for_clients {
my ( $sock, $client );
- # Set up the socket to listen to
+ $SIG{'CHLD'} = 'IGNORE';
$SIG{'PIPE'} = 'IGNORE';
$SIG{'TERM'} = $SIG{'HUP'} = $SIG{'QUIT'} = sub {
&debug('spong client caught QUIT signal, exiting',3);
undef $sock; exit;
};
+ # Set up the socket to listen to
$sock = IO::Socket::INET->new( Listen => SOMAXCONN,
LocalPort => $main::SPONG_CLIENT_PORT,
Proto => 'tcp',
sub listen_for_updates {
+ $SIG{'CHLD'} = 'IGNORE';
$SIG{'PIPE'} = 'IGNORE';
$SIG{'QUIT'} = sub {&debug('spong updates caught QUIT signal, exiting');
- close SERVER; exit;};
+ close $sock; exit;};
$SIG{'HUP'} = sub {&debug('spong updates caught HUP signal, exiting');
- close SERVER; exit;};
+ close $sock; exit;};
# Set up the socket to listen to
&debug( "update server socket setup, listening for connections" );
while( 1 ) {
+
+ $0 = "spong-server (spong-update) accepting connections on $SPONG_UPDATE_PORT";
+
+ # Try to accept the next connection
next unless ( $client = $sock->accept() );
+
my $paddr = $client->peerhost();
&debug("Connection from $paddr",6);
+ $0 = "spong-server (spong-update) connection from $paddr";
# &validate_connection( $paddr ); - need to do something here...
- # Read all from the client, and disconnect, we process the message next.
-
- my( $header, $ok ) = ( "", 0 );
- my( $message, $cnt, $line ) = ( "", "", "" );
-
- # Set an alarm on this block in case the client runs into problems
- eval
- {
- local $SIG{'ALRM'} = sub { die; };
- alarm($SPONG_SERVER_ALARM) if $SPONG_SERVER_ALARM;
-
- $header = <$client>; chomp $header;
- &debug("msg header = $header",6);
- while( defined( $line = <$client> ) ) {
- last if ($cnt += length($line)) > 100000;
- $message .= $line;
- }
-
- alarm(0);
- $ok = 1;
- };
- undef $client;
-
- if ( ! $ok ) {
- &error( "ss_update: Connection from $paddr timed out" );
- next;
- }
-
- # Now depending on what kind of message it is, pass it off to a routine
- # that can process the message. Currently valid messages are "status",
- # "ack", "config", and "stat".
-
- if( $header =~ /^status\b/ ) { &save_status( $header, $message ); next; }
- if( $header =~ /^ack-del\b/ ) { &del_ack( $header, $message ); next; }
- if( $header =~ /^ack\b/ ) { &save_ack( $header, $message ); next; }
- # if( $header =~ /^config\b/ ) { &save_config( $header, $message ); }
- # if( $header =~ /^stat\b/ ) { &save_stat( $header, $message ); }
+ # Now fork and allow the kid to process the message
+ my $pid = fork();
+ if ( ! defined $pid) { &error("listen_for_updates: Could not fork: $!"); }
+ elsif ( $pid ) { } # I'm the parent
+ else { # I'm the kid
+
+ # Read all from the client, and disconnect
+
+ my( $header, $ok ) = ( "", 0 );
+ my( $message, $cnt, $line ) = ( "", "", "" );
+
+ # Set an alarm on this block in case the client runs into problems
+ eval
+ {
+ local $SIG{'ALRM'} = sub { die; };
+ alarm($SPONG_SERVER_ALARM) if $SPONG_SERVER_ALARM;
+
+ $header = <$client>; chomp $header;
+ &debug("msg header = $header",6);
+ while( defined( $line = <$client> ) ) {
+ last if ($cnt += length($line)) > 100000;
+ $message .= $line;
+ }
+
+ alarm(0);
+ $ok = 1;
+ };
+ undef $client;
+
+ if ( ! $ok ) {
+ &error( "ss_update: Connection from $paddr timed out" );
+ exit;
+ }
+
+ # Now depending on what kind of message it is, pass it off to a routine
+ # that can process the message. Currently valid messages are "status",
+ # "ack", "config", and "stat".
+
+ if( $header =~ /^status\b/ ) { &save_status( $header, $message ); }
+ if( $header =~ /^ack-del\b/ ) { &del_ack( $header, $message ); }
+ if( $header =~ /^ack\b/ ) { &save_ack( $header, $message ); }
+ # if( $header =~ /^config\b/ ) { &save_config( $header, $message ); }
+ # if( $header =~ /^stat\b/ ) { &save_stat( $header, $message ); }
+
+ exit;
+ } # End child processing
+ } continue {
+# undef $client;
}
}
sub listen_for_bb_updates {
+ $SIG{'CHLD'} = 'IGNORE';
$SIG{'PIPE'} = 'IGNORE';
$SIG{'TERM'} = $SIG{'HUP'} = $SIG{'QUIT'} = sub {
&debug('spong updates caught signal, exiting',3);
&debug( "bb update server socket setup, listening for connections" );
while( 1 ) {
+
+ $0 = "spong-server (spong-bb-update) accepting connections on $SPONG_BB_UPDATE_PORT";
+
+ # Try to accept the next connection
next unless ( $client = $sock->accept() );
+
my $paddr = $client->peerhost();
+ &debug("Connection from $paddr",6);
+ $0 = "spong-server (spong-bb-update) connection from $paddr";
# &validate_connection( $paddr ); - need to do something here...
- # Read all from the client, and disconnect, we process the message next.
- my( $header, $ok ) = ( "", 0 );
- my( $message, $cnt, $line ) = ( "", "", "" );
+ # Now fork and allow the kid to process the message
+ my $pid = fork();
+ if ( ! defined $pid) { &error("listen_for_bb_updates: Coulnd not fork: $!"); }
+ elsif ( $pid ) { } # I'm the parent
+ else { # I'm the child
- eval {
- local $SIG{'ALRM'} = sub { die; };
- alarm($SPONG_SERVER_ALARM) if $SPONG_SERVER_ALARM;
+ # Read all from the client, and disconnect,
+ my( $header, $ok ) = ( "", 0 );
+ my( $message, $cnt, $line ) = ( "", "", "" );
- $header = <$client>; chomp $header;
- while( defined( $line = <$client> ) ) {
- last if ($cnt += length($line)) > 100000;
- $message .= $line;
- }
+ eval {
+ local $SIG{'ALRM'} = sub { die; };
+ alarm($SPONG_SERVER_ALARM) if $SPONG_SERVER_ALARM;
- $ok = 1;
- };
- alarm(0);
- undef $client;
+ $header = <$client>; chomp $header;
+ while( defined( $line = <$client> ) ) {
+ last if ($cnt += length($line)) > 100000;
+ $message .= $line;
+ }
- if ( ! $ok ) {
- &error( "ss_update: Connection from $paddr timed out" );
- next;
- }
+ $ok = 1;
+ alarm(0);
+ };
+ undef $client;
- &debug($message,8);
+ if ( ! $ok ) {
+ &error( "ss_update: Connection from $paddr timed out" );
+ exit;
+ }
- # Now depending on what kind of message it is, pass it off to a routine
- # that can process the message.
+ &debug($message,8);
- if( $header =~ /^status\b/ ) {
- &save_bb_status( $header, $message );
- next;
+ # Now depending on what kind of message it is, pass it off to a routine
+ # that can process the message.
+
+ if( $header =~ /^status\b/ ) {
+ &save_bb_status( $header, $message );
+ }
+
+ exit;
}
}
}
sub listen_for_queries {
+ $SIG{'CHLD'} = 'IGNORE';
$SIG{'PIPE'} = 'IGNORE';
$SIG{'TERM'} = $SIG{'HUP'} = $SIG{'QUIT'} = sub {
&debug('spong updates caught QUIT signal, exiting',3);
$main::SERVICES{$service}=1;}}
$next_update =+ 15 * 60;
}
+
+
next unless ( $client = $sock->accept() );
+
my $paddr = $client->peerhost();
+ &debug("[$$] update: Connection from $paddr",6);
+ $0 = "spong-server (query) connection from $paddr";
# &validate_connection( $paddr ); - need to do something here...
- # Read the entire query from the client, don't disconnect like we do with
- # updates however, as we need to send back some information. Query
- # requests are simple one line messages.
- my $header = <$client>; chomp $header; $header =~ s/\r//;
- my( $query, $hosts, $type, $view, $other ) =
- ( $header =~ /^(\w+)\s+\[([^\]]*)\]\s+(\w+)\s+(\w+)\b\s*(.*)$/ );
+ # Now fork and allow the kid to process the message
+ my $pid = fork();
+ if ( ! defined $pid) { &error("list_for_queries: Could not fork: $!"); }
+ elsif ($pid) { } # I'm the parent, do nothing
+ else { # I'm the kid
- # Now depending on what kind of request it is, pass it off to a routine
- # that can process the message.
+ # Read the entire query from the client, don't disconnect like we do
+ # with updates however, as we need to send back some information.
+ # Query requests are simple one line messages.
- my( @args ) = ( $hosts, $type, $view ); # Just shortens up the code...
- my $output = select $client;
+ my $header = <$client>; chomp $header; $header =~ s/\r//;
+ my( $query, $hosts, $type, $view, $other ) =
+ ( $header =~ /^(\w+)\s+\[([^\]]*)\]\s+(\w+)\s+(\w+)\b\s*(.*)$/ );
- &debug( "[$$] showing $query information for $hosts [$type:$view]" );
+ # Now depending on what kind of request it is, pass it off to a routine
+ # that can process the message.
- if( $query eq "problems" ) { &show_problems( @args ); }
-# Disabled for now into all of Herbie's web enchanges are added
-# if( $query eq "warnings" ) { &show_warnings( @args ); }
- if( $query eq "summary" ) { &show_summary( @args ); }
- if( $query eq "history" ) { &show_history( @args ); }
- if( $query eq "host" ) { &show_host( @args ); }
- if( $query eq "services" ) { &show_services( @args ); }
- if( $query eq "acks" ) { &show_acks( @args ); }
- if( $query eq "stats" ) { &show_stats( @args ); }
- if( $query eq "config" ) { &show_config( @args ); }
- if( $query eq "info" ) { &show_info( @args ); }
- if( $query eq "service" ) { &show_service( @args, $other ); }
- if( $query eq "histservice" ) { &show_hist_service( @args, $other ); }
- if( $query eq "overview" ) { &show_overview( @args, $other ); }
- if( $query eq "ovproblems" ) { &show_ovproblems( @args, $other ); }
+ my( @args ) = ( $hosts, $type, $view ); # Just shortens up the code...
+ my $output = select $client;
- undef $client;
- select $output;
+ &debug( "[$$] showing $query information for $hosts [$type:$view]" );
+
+ if( $query eq "problems" ) { &show_problems( @args ); }
+# Disabled for now into all of Herbie's web enchanges are added
+# if( $query eq "warnings" ) { &show_warnings( @args ); }
+ if( $query eq "summary" ) { &show_summary( @args ); }
+ if( $query eq "history" ) { &show_history( @args ); }
+ if( $query eq "host" ) { &show_host( @args ); }
+ if( $query eq "services" ) { &show_services( @args ); }
+ if( $query eq "acks" ) { &show_acks( @args ); }
+ if( $query eq "stats" ) { &show_stats( @args ); }
+ if( $query eq "config" ) { &show_config( @args ); }
+ if( $query eq "info" ) { &show_info( @args ); }
+ if( $query eq "service" ) { &show_service( @args, $other ); }
+ if( $query eq "histservice" ) { &show_hist_service( @args, $other ); }
+ if( $query eq "overview" ) { &show_overview( @args, $other ); }
+ if( $query eq "ovproblems" ) { &show_ovproblems( @args, $other ); }
+
+ undef $client;
+ select $output;
+ exit;
+
+ } # End of kid processing
}
}
&debug( 'Shutting down, not restarting children',2);
return;
}
- &debug( "caught CHLD signal, restarting child..." );
+ &debug( "caught CHLD signal, exit status $?, restarting " );
while( my($name,$proc) = each %PROCS ) {
if ( $pid == $proc->{'pid'} ) {
}
+# Child reaper for the forking server processes. It just reaps expired
+# child processes to prevent zombies from accumulating.
+
+sub reaper {
+ my $kid;
+
+ $kid = wait();
+ $main::numchild--;
+ &debug("reaped kid $kid, # of child = $main::numchild");
+
+# while( ($kid = waitpid(-1,&WNOHANG)) > 0 ) {
+# $main::numchild--;
+# &debug("reaped kid $kid, # of child = $main::numchild");
+# }
+
+ # Reinstate signal handler in cae system uses sysV libs
+ $SIG{'CHLD'} = \&reaper;
+}
+
# ---------------------------------------------------------------------------
# Load all of the data functions into the DATAFUNCS registry
# ---------------------------------------------------------------------------