Changeset fdf483da922d0f49378f342daf5047f3686b9209

Show
Ignore:
Timestamp:
02/18/10 22:22:44 (9 years ago)
Author:
Mark Harrison <mark@omniti.com>
git-committer:
Mark Harrison <mark@omniti.com> 1266531764 +0000
git-parent:

[d5d5b4929dbf98f5a8953bcc43f6c24007be7b5f]

git-author:
Mark Harrison <mark@omniti.com> 1266531764 +0000
Message:

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).

git-svn-id: https://labs.omniti.com/resmon/trunk@240 8c0face9-b7db-6ec6-c4b3-d5f7145c7d55

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • lib/Resmon/ExtComm.pm

    rb3c6407 rfdf483d  
    1010my %commhist; 
    1111my %commcache; 
     12my %children; 
    1213 
    1314sub cache_command($$;$) { 
     
    2021  } 
    2122  # TODO: timeouts 
    22   $commcache{$command} = `$command`
     23  $commcache{$command} = run_cmd($command)
    2324  $commhist{$command} = $now + $expiry; 
    2425  return $commcache{$command}; 
    2526} 
    2627 
     28sub clean_up { 
     29    # Kill off any child processes started by run_cmd and close any pipes to 
     30    # them. This is called when a check times out and we may have processes 
     31    # left over. 
     32    while (my ($pid, $handle) = each %children) { 
     33        kill 9, $pid; 
     34        close ($handle); 
     35        delete $children{$pid}; 
     36    } 
     37} 
     38 
     39sub run_cmd { 
     40    # Run a command just like `cmd`, but store the pid and stdout handles so 
     41    # they can be cleaned up later. For use with alarm(). 
     42    my $cmd = shift; 
     43    pipe(my ($r, $w)); 
     44    my $pid = fork(); 
     45    if($pid) { 
     46        close($w); 
     47        $children{$pid} = $r; 
     48        my @lines = <$r>; 
     49        waitpid($pid, 0); 
     50        delete $children{$pid}; 
     51        return join('\n', @lines); 
     52    } else { 
     53        eval { 
     54            open(STDOUT, ">&", $w); 
     55            close($r); 
     56            exec($cmd); 
     57        }; 
     58        exit(); 
     59    } 
     60} 
     61 
    27621; 
  • lib/Resmon/Module/DHCPLEASES.pm

    r44f41a8 rfdf483d  
    11package Resmon::Module::DHCPLEASES; 
    2 use Resmon::ExtComm qw/cache_command/; 
     2use Resmon::ExtComm qw/cache_command run_cmd/; 
    33use vars qw/@ISA/; 
    44@ISA = qw/Resmon::Module/; 
     
    1010  my %ips; 
    1111  open (IN, '<', $file); 
    12   my $date = `date -u +'%Y/%m/%d %H:%M:%S;'`
     12  my $date = run_cmd("date -u +'%Y/%m/%d %H:%M:%S;'")
    1313  my ($actives,$mynet,$ip,$starts,$ends)=(0,'','','',''); 
    1414  while (<IN>) { 
  • lib/Resmon/Module/FREEMEM.pm

    r998c234 rfdf483d  
    2020 
    2121use Resmon::Module; 
     22use Resmon::ExtComm qw/cache_command run_cmd/; 
    2223 
    2324use vars qw/@ISA/; 
     
    6465            } 
    6566            # Get free memory using vmstat 
    66             my @vmstat = `/usr/bin/vmstat 1 2`
     67            my @vmstat = run_cmd("/usr/bin/vmstat 1 2")
    6768            my $line = $vmstat[-1]; 
    6869            chomp($line); 
     
    7172 
    7273            # Get total memory using prtconf 
    73             my @prtconf = `/usr/sbin/prtconf 2>/dev/null`
     74            my @prtconf = run_cmd("/usr/sbin/prtconf 2>/dev/null")
    7475            foreach (@prtconf) { 
    7576                if (/^Memory size: (\d+) Megabytes/) { 
     
    7980        } else { 
    8081            # We have kstat, use that for everything 
    81             my $pagesize = `pagesize`
     82            my $pagesize = run_cmd("pagesize")
    8283            my $syspages = $kstat->{unix}->{0}->{system_pages}; 
    8384            $total_mem = $syspages->{physmem} * $pagesize / 1024 / 1024; 
  • lib/Resmon/Module/FRESHSVN.pm

    rf8f9000 rfdf483d  
    11package Resmon::Module::FRESHSVN; 
    22use strict; 
    3 use Resmon::ExtComm qw/cache_command/; 
     3use Resmon::ExtComm qw/cache_command run_cmd/; 
    44use vars qw/@ISA/; 
    55use File::Find; 
     
    3636  if($ur <= $mr){ return "OK(rev:$ur)"; } 
    3737  else{ 
    38     my ($cY,$cM,$cD,$ch,$cm,$cs) = split (/ /, `date '+%Y %m %d %H %M %S'`); 
     38    my ($cY,$cM,$cD,$ch,$cm,$cs) = split (/ /, 
     39        run_cmd("date '+%Y %m %d %H %M %S'")); 
    3940    my $cTime=$cs+60*($cm+60*($ch+24*($cD+31*($cM+12*$cY)))); 
    4041    my $dNow = "$cM/$cD/$cY $ch:$cm:$cs"; chomp $dNow; 
  • lib/Resmon/Module/NAGIOS.pm

    ref61481 rfdf483d  
    11package Resmon::Module::NAGIOS; 
     2use Resmon::ExtComm qw/cache_command run_cmd/; 
    23use vars qw/@ISA/; 
    34@ISA = qw/Resmon::Module/; 
     
    1415    my $script = $arg->{'object'} || return "BAD", "No script specified"; 
    1516    my $scriptargs = $arg->{'args'}; 
    16     my $output = `$script $scriptargs`
     17    my $output = run_cmd("$script $scriptargs")
    1718    my $retval = $?; 
    1819    if ($retval == -1) { 
  • lib/Resmon/Module/SPARCTEMP.pm

    r0cac135 rfdf483d  
    11package Resmon::Module::SPARCTEMP; 
    2 use Resmon::ExtComm qw/cache_command/; 
     2use Resmon::ExtComm qw/cache_command run_cmd/; 
    33use vars qw/@ISA/; 
    44@ISA = qw/Resmon::Module/; 
     
    1212  print STDERR "command=$command\n" if $DEBUG; 
    1313  my $output = cache_command($command, 30); 
    14  # my $output = `/usr/sbin/prtpicl -v -c temperature-sensor`
     14 # my $output = run_cmd("/usr/sbin/prtpicl -v -c temperature-sensor")
    1515  print STDERR $output if $DEBUG>1; 
    1616  my @lines = split(/\n/, $output); 
  • resmon

    rd5d5b49 rfdf483d  
    164164          $results->{metric} = { "message" => 
    165165              "Check timeout"}; 
     166          Resmon::ExtComm::clean_up; 
    166167        } 
    167168      } else {