From 10c17bd3ade48e9f9fdf99dd3be6c6fdd176158d Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Mon, 20 Apr 2015 21:33:01 -0700 Subject: [PATCH] Add watchdog to monitor VM cpu load and reset for excessive load Detect if VM is running under excessive load (e.g., due to fork bombing) for longer than a certain period and reset the VM state if so. --- doc/MODULES | 1 + .../compiler_vm/compiler_server_watchdog.pl | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100755 modules/compiler_vm/compiler_server_watchdog.pl diff --git a/doc/MODULES b/doc/MODULES index baa4298a..4eff4c81 100644 --- a/doc/MODULES +++ b/doc/MODULES @@ -14,6 +14,7 @@ LWP::Simple LWP::UserAgent LWP::UserAgent::WithCache Net::Dict +Proc::ProcessTable SOAP::Lite Text::Autoformat Text::Balanced diff --git a/modules/compiler_vm/compiler_server_watchdog.pl b/modules/compiler_vm/compiler_server_watchdog.pl new file mode 100755 index 00000000..5e8ddde3 --- /dev/null +++ b/modules/compiler_vm/compiler_server_watchdog.pl @@ -0,0 +1,59 @@ +#!/usr/bin/env perl + +use warnings; +use strict; + +use Proc::ProcessTable; +use IO::Socket; + +my $SLEEP = 15; +my $MAX_PCTCPU = 25; +my $QEMU = 'qemu-system-x86'; +my $MONITOR_PORT = 3335; + +my $last_pctcpu = 0; + +sub reset_vm { + print "Resetting vm\n"; + + my $sock = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => $MONITOR_PORT, Prot => 'tcp'); + if(not defined $sock) { + print "[vm_reset] Unable to connect to monitor: $!\n"; + return; + } + + print $sock "loadvm 1\n"; + close $sock; + + print "Reset vm\n"; +} + +while (1) { + my $t = new Proc::ProcessTable(enable_ttys => 0); + + my ($pids, $p); + + foreach $p (@{$t->table}) { + $pids->{$p->pid} = { fname => $p->fname, ppid => $p->ppid }; + } + + foreach $p (keys %$pids) { + if ($pids->{$p}->{fname} eq $QEMU) { + my $ppid = $pids->{$p}->{ppid}; + if ($pids->{$ppid}->{fname} eq 'compiler_server') { + my $pctcpu = `top -b -n 1 -p $p | tail -n 1 | awk '{print \$9}'`; + $pctcpu =~ s/^\s+|\s+$//g; + print scalar localtime, " :: Got compiler qemu pid: $p; using $pctcpu cpu\n"; + + if ($pctcpu >= $last_pctcpu and $last_pctcpu >= $MAX_PCTCPU) { + reset_vm; + $last_pctcpu = 0; + } else { + $last_pctcpu = $pctcpu; + } + } + } + } + + sleep $SLEEP; +}