[Resmon-devel] [resmon commit] r240 - in trunk: . lib/Resmon lib/Resmon/Module

svn-commit at lists.omniti.com svn-commit at lists.omniti.com
Thu Feb 18 17:22:44 EST 2010


Author: mark
Date: 2010-02-18 17:22:44 -0500 (Thu, 18 Feb 2010)
New Revision: 240

Modified:
   trunk/lib/Resmon/ExtComm.pm
   trunk/lib/Resmon/Module/DHCPLEASES.pm
   trunk/lib/Resmon/Module/FREEMEM.pm
   trunk/lib/Resmon/Module/FRESHSVN.pm
   trunk/lib/Resmon/Module/NAGIOS.pm
   trunk/lib/Resmon/Module/SPARCTEMP.pm
   trunk/resmon
Log:
Fix for filehandles not being cleaned up after a check timeout

When a check times out using alarm, any processes launched using cache_command
or backticks would still be running, and leave a pipe open, even after the
process exits. This change keeps track of any child processes, and will kill
them off and clean up the pipe if a check timeout occurs. Modules that use
cache_command do not need any modification, but modules that use backticks
should change to using Resmon::ExtComm::run_cmd, which is a drop in
replacement. (use run_cmd("command") instead of `command`).

Modified: trunk/lib/Resmon/ExtComm.pm
===================================================================
--- trunk/lib/Resmon/ExtComm.pm	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/lib/Resmon/ExtComm.pm	2010-02-18 22:22:44 UTC (rev 240)
@@ -9,6 +9,7 @@
 
 my %commhist;
 my %commcache;
+my %children;
 
 sub cache_command($$;$) {
   my ($command, $expiry, $timeout) = @_;
@@ -19,9 +20,43 @@
     return $commcache{$command};
   }
   # TODO: timeouts
-  $commcache{$command} = `$command`;
+  $commcache{$command} = run_cmd($command);
   $commhist{$command} = $now + $expiry;
   return $commcache{$command};
 }
 
+sub clean_up {
+    # Kill off any child processes started by run_cmd and close any pipes to
+    # them. This is called when a check times out and we may have processes
+    # left over.
+    while (my ($pid, $handle) = each %children) {
+        kill 9, $pid;
+        close ($handle);
+        delete $children{$pid};
+    }
+}
+
+sub run_cmd {
+    # Run a command just like `cmd`, but store the pid and stdout handles so
+    # they can be cleaned up later. For use with alarm().
+    my $cmd = shift;
+    pipe(my ($r, $w));
+    my $pid = fork();
+    if($pid) {
+        close($w);
+        $children{$pid} = $r;
+        my @lines = <$r>;
+        waitpid($pid, 0);
+        delete $children{$pid};
+        return join('\n', @lines);
+    } else {
+        eval {
+            open(STDOUT, ">&", $w);
+            close($r);
+            exec($cmd);
+        };
+        exit();
+    }
+}
+
 1;

Modified: trunk/lib/Resmon/Module/DHCPLEASES.pm
===================================================================
--- trunk/lib/Resmon/Module/DHCPLEASES.pm	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/lib/Resmon/Module/DHCPLEASES.pm	2010-02-18 22:22:44 UTC (rev 240)
@@ -1,5 +1,5 @@
 package Resmon::Module::DHCPLEASES;
-use Resmon::ExtComm qw/cache_command/;
+use Resmon::ExtComm qw/cache_command run_cmd/;
 use vars qw/@ISA/;
 @ISA = qw/Resmon::Module/;
 
@@ -9,7 +9,7 @@
   my $file = "/var/db/dhcpd.leases";
   my %ips;
   open (IN, '<', $file);
-  my $date = `date -u +'%Y/%m/%d %H:%M:%S;'`;
+  my $date = run_cmd("date -u +'%Y/%m/%d %H:%M:%S;'");
   my ($actives,$mynet,$ip,$starts,$ends)=(0,'','','','');
   while (<IN>) {
     if (/^lease/) {

Modified: trunk/lib/Resmon/Module/FREEMEM.pm
===================================================================
--- trunk/lib/Resmon/Module/FREEMEM.pm	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/lib/Resmon/Module/FREEMEM.pm	2010-02-18 22:22:44 UTC (rev 240)
@@ -19,6 +19,7 @@
 use warnings;
 
 use Resmon::Module;
+use Resmon::ExtComm qw/cache_command run_cmd/;
 
 use vars qw/@ISA/;
 @ISA = qw/Resmon::Module/;
@@ -63,14 +64,14 @@
                 return "BAD", "Kstat not available - can't report on arc size";
             }
             # Get free memory using vmstat
-            my @vmstat = `/usr/bin/vmstat 1 2`;
+            my @vmstat = run_cmd("/usr/bin/vmstat 1 2");
             my $line = $vmstat[-1];
             chomp($line);
             my @parts = split(/ /,$line);
             $free_mem = $parts[5] / 1024;
 
             # Get total memory using prtconf
-            my @prtconf = `/usr/sbin/prtconf 2>/dev/null`;
+            my @prtconf = run_cmd("/usr/sbin/prtconf 2>/dev/null");
             foreach (@prtconf) {
                 if (/^Memory size: (\d+) Megabytes/) {
                     $total_mem = $1;
@@ -78,7 +79,7 @@
             }
         } else {
             # We have kstat, use that for everything
-            my $pagesize = `pagesize`;
+            my $pagesize = run_cmd("pagesize");
             my $syspages = $kstat->{unix}->{0}->{system_pages};
             $total_mem = $syspages->{physmem} * $pagesize / 1024 / 1024;
             $free_mem  = $syspages->{freemem} * $pagesize / 1024 / 1024;

Modified: trunk/lib/Resmon/Module/FRESHSVN.pm
===================================================================
--- trunk/lib/Resmon/Module/FRESHSVN.pm	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/lib/Resmon/Module/FRESHSVN.pm	2010-02-18 22:22:44 UTC (rev 240)
@@ -1,6 +1,6 @@
 package Resmon::Module::FRESHSVN;
 use strict;
-use Resmon::ExtComm qw/cache_command/;
+use Resmon::ExtComm qw/cache_command run_cmd/;
 use vars qw/@ISA/;
 use File::Find;
 
@@ -35,7 +35,8 @@
   if(!$ur){ return "BAD(Unable to determine latest revision in repository)"; }
   if($ur <= $mr){ return "OK(rev:$ur)"; }
   else{
-    my ($cY,$cM,$cD,$ch,$cm,$cs) = split (/ /, `date '+%Y %m %d %H %M %S'`);
+    my ($cY,$cM,$cD,$ch,$cm,$cs) = split (/ /,
+        run_cmd("date '+%Y %m %d %H %M %S'"));
     my $cTime=$cs+60*($cm+60*($ch+24*($cD+31*($cM+12*$cY))));
     my $dNow = "$cM/$cD/$cY $ch:$cm:$cs"; chomp $dNow;
     my ($uY,$uM,$uD,$uh,$um,$us);

Modified: trunk/lib/Resmon/Module/NAGIOS.pm
===================================================================
--- trunk/lib/Resmon/Module/NAGIOS.pm	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/lib/Resmon/Module/NAGIOS.pm	2010-02-18 22:22:44 UTC (rev 240)
@@ -1,4 +1,5 @@
 package Resmon::Module::NAGIOS;
+use Resmon::ExtComm qw/cache_command run_cmd/;
 use vars qw/@ISA/;
 @ISA = qw/Resmon::Module/;
 
@@ -13,7 +14,7 @@
     my $arg = shift;
     my $script = $arg->{'object'} || return "BAD", "No script specified";
     my $scriptargs = $arg->{'args'};
-    my $output = `$script $scriptargs`;
+    my $output = run_cmd("$script $scriptargs");
     my $retval = $?;
     if ($retval == -1) {
         return "BAD", "command returning -1";

Modified: trunk/lib/Resmon/Module/SPARCTEMP.pm
===================================================================
--- trunk/lib/Resmon/Module/SPARCTEMP.pm	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/lib/Resmon/Module/SPARCTEMP.pm	2010-02-18 22:22:44 UTC (rev 240)
@@ -1,5 +1,5 @@
 package Resmon::Module::SPARCTEMP;
-use Resmon::ExtComm qw/cache_command/;
+use Resmon::ExtComm qw/cache_command run_cmd/;
 use vars qw/@ISA/;
 @ISA = qw/Resmon::Module/;
 
@@ -11,7 +11,7 @@
   my $command = "/usr/sbin/prtpicl -v -c temperature-sensor";
   print STDERR "command=$command\n" if $DEBUG;
   my $output = cache_command($command, 30);
- # my $output = `/usr/sbin/prtpicl -v -c temperature-sensor`;
+ # my $output = run_cmd("/usr/sbin/prtpicl -v -c temperature-sensor");
   print STDERR $output if $DEBUG>1;
   my @lines = split(/\n/, $output);
   print STDERR join("\nlines", @lines) if $DEBUG>1;

Modified: trunk/resmon
===================================================================
--- trunk/resmon	2010-02-18 20:16:12 UTC (rev 239)
+++ trunk/resmon	2010-02-18 22:22:44 UTC (rev 240)
@@ -163,6 +163,7 @@
         if ($checkstat eq "alarm\n") {
           $results->{metric} = { "message" =>
               "Check timeout"};
+          Resmon::ExtComm::clean_up;
         }
       } else {
         $results->{state} = $check_rv;



More information about the Resmon-devel mailing list