From 55a8f6f339111317c62c4bf08ee882403fb5e835 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Fri, 14 Nov 2014 10:51:51 -0600 Subject: [PATCH 1/2] Remove Msf::DBManager::Sink MSP-11614 `Msf::DBManager::Sink` contains code for a `sink` that is a meant to serialize database events, but it's unneeded because all database events go directly through ActiveRecord, which handles threading. --- lib/msf/core/db_manager.rb | 7 ---- lib/msf/core/db_manager/sink.rb | 34 ------------------- spec/lib/msf/db_manager_spec.rb | 1 - .../shared/examples/msf/db_manager/sink.rb | 7 ---- 4 files changed, 49 deletions(-) delete mode 100644 lib/msf/core/db_manager/sink.rb delete mode 100644 spec/support/shared/examples/msf/db_manager/sink.rb diff --git a/lib/msf/core/db_manager.rb b/lib/msf/core/db_manager.rb index 423211ee64..e3027bedba 100644 --- a/lib/msf/core/db_manager.rb +++ b/lib/msf/core/db_manager.rb @@ -47,7 +47,6 @@ class Msf::DBManager autoload :Service, 'msf/core/db_manager/service' autoload :Session, 'msf/core/db_manager/session' autoload :SessionEvent, 'msf/core/db_manager/session_event' - autoload :Sink, 'msf/core/db_manager/sink' autoload :Task, 'msf/core/db_manager/task' autoload :Vuln, 'msf/core/db_manager/vuln' autoload :VulnAttempt, 'msf/core/db_manager/vuln_attempt' @@ -80,7 +79,6 @@ class Msf::DBManager include Msf::DBManager::Service include Msf::DBManager::Session include Msf::DBManager::SessionEvent - include Msf::DBManager::Sink include Msf::DBManager::Task include Msf::DBManager::Vuln include Msf::DBManager::VulnAttempt @@ -160,11 +158,6 @@ class Msf::DBManager # initialize_adapter - # - # Instantiate the database sink - # - initialize_sink - true end diff --git a/lib/msf/core/db_manager/sink.rb b/lib/msf/core/db_manager/sink.rb deleted file mode 100644 index 25d05baee5..0000000000 --- a/lib/msf/core/db_manager/sink.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Msf::DBManager::Sink - # - # Attributes - # - - # Stores a TaskManager for serializing database events - attr_accessor :sink - - # - # Instance Methods - # - - # - # Create a new database sink and initialize it - # - def initialize_sink - self.sink = Msf::TaskManager.new(framework) - self.sink.start - end - - # - # Add a new task to the sink - # - def queue(proc) - self.sink.queue_proc(proc) - end - - # - # Wait for all pending write to finish - # - def sync - # There is no more queue. - end -end \ No newline at end of file diff --git a/spec/lib/msf/db_manager_spec.rb b/spec/lib/msf/db_manager_spec.rb index b3f2d69877..2c732c9281 100644 --- a/spec/lib/msf/db_manager_spec.rb +++ b/spec/lib/msf/db_manager_spec.rb @@ -40,7 +40,6 @@ describe Msf::DBManager do it_should_behave_like 'Msf::DBManager::Service' it_should_behave_like 'Msf::DBManager::Session' it_should_behave_like 'Msf::DBManager::SessionEvent' - it_should_behave_like 'Msf::DBManager::Sink' it_should_behave_like 'Msf::DBManager::Task' it_should_behave_like 'Msf::DBManager::Vuln' it_should_behave_like 'Msf::DBManager::VulnAttempt' diff --git a/spec/support/shared/examples/msf/db_manager/sink.rb b/spec/support/shared/examples/msf/db_manager/sink.rb deleted file mode 100644 index af9eb81a46..0000000000 --- a/spec/support/shared/examples/msf/db_manager/sink.rb +++ /dev/null @@ -1,7 +0,0 @@ -shared_examples_for 'Msf::DBManager::Sink' do - it { is_expected.to respond_to :initialize_sink } - it { is_expected.to respond_to :queue } - it { is_expected.to respond_to :sink } - it { is_expected.to respond_to :sink= } - it { is_expected.to respond_to :sync } -end \ No newline at end of file From 5e6400a506df9c0510edd11aa3864602312c266f Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Fri, 14 Nov 2014 11:15:05 -0600 Subject: [PATCH 2/2] Remove Msf::TaskManager MSP-11614 `Msf::TaskManager` was only used for `Msf::DBManager#sink`, which was removed because it was unused, so `Msf::TaskManager` can also be removed. --- lib/msf/core/db_manager.rb | 1 - lib/msf/core/task_manager.rb | 238 ------------------------- spec/lib/msf/core/task_manager_spec.rb | 99 ---------- 3 files changed, 338 deletions(-) delete mode 100644 lib/msf/core/task_manager.rb delete mode 100644 spec/lib/msf/core/task_manager_spec.rb diff --git a/lib/msf/core/db_manager.rb b/lib/msf/core/db_manager.rb index e3027bedba..2bc00061ee 100644 --- a/lib/msf/core/db_manager.rb +++ b/lib/msf/core/db_manager.rb @@ -17,7 +17,6 @@ require 'msf/core/database_event' require 'msf/core/db_import_error' require 'msf/core/host_state' require 'msf/core/service_state' -require 'msf/core/task_manager' # The db module provides persistent storage and events. This class should be instantiated LAST # as the active_suppport library overrides Kernel.require, slowing down all future code loads. diff --git a/lib/msf/core/task_manager.rb b/lib/msf/core/task_manager.rb deleted file mode 100644 index 54f6399608..0000000000 --- a/lib/msf/core/task_manager.rb +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: binary -*- -module Msf - -### -# -# This class provides a task manager -# -### - -class TaskManager - - class Task - attr_accessor :timeout - attr_accessor :created - attr_accessor :completed - attr_accessor :status - attr_accessor :proc - attr_accessor :source - attr_accessor :exception - - # - # Create a new task - # - def initialize(proc,timeout=nil) - self.proc = proc - self.status = :new - self.created = Time.now - self.timeout = timeout - self.source = caller - end - - # - # Task duration in seconds (float) - # - def duration - etime = self.completed || Time.now - etime.to_f - self.created.to_f - end - - def wait - while self.status == :new - ::IO.select(nil,nil,nil,0.10) - end - return self.status - end - - # - # Run the associated proc - # - def run(*args) - self.proc.call(*args) if self.proc - end - - end - - - attr_accessor :processing - attr_accessor :queue - attr_accessor :thread - attr_accessor :framework - - # - # Create a new TaskManager - # - def initialize(framework) - self.framework = framework - self.flush - end - - # - # Add a new task via proc - # - def queue_proc(proc) - task = Task.new(proc) - queue_task(task) - return task - end - - # - # Add a new task to the queue unless we are called - # by the queue thread itself. - # - def queue_task(task) - if Thread.current[:task_manager] - process_task(task) - else - self.queue.push(task) - end - end - - # - # Flush the queue - # - def flush - self.queue = [] - end - - # - # Stop processing events - # - def stop - return if not self.thread - self.processing = false - self.thread.join - self.thread = nil - end - - # - # Forcefully kill the processing thread - # - def kill - return if not self.thread - self.processing = false - self.thread.kill - self.thread = nil - end - - # - # Start processing tasks - # - def start - return if self.thread - self.processing = true - self.thread = framework.threads.spawn("TaskManager", true) do - begin - process_tasks - rescue ::Exception => e - elog("taskmanager: process_tasks exception: #{e.class} #{e} #{e.backtrace}") - retry - end - end - - # Mark this thread as the task manager - self.thread[:task_manager] = true - - # Return the thread object to the caller - self.thread - end - - # - # Restart the task processor - # - def restart - stop - start - end - - # - # Retrieve the number of tasks in the queue - # - def backlog - self.queue.length - end - - # - # Process the actual queue - # - def process_tasks - spin = 50 - ltask = nil - - while(self.processing) - cnt = 0 - while(task = self.queue.shift) - stime = Time.now.to_f - ret = process_task(task) - etime = Time.now.to_f - - case ret - when :requeue - self.queue.push(task) - when :drop, :done - # Processed or dropped - end - cnt += 1 - - ltask = task - end - - spin = (cnt == 0) ? (spin + 1) : 0 - - if spin > 10 - ::IO.select(nil, nil, nil, 0.25) - end - - end - self.thread = nil - end - - # - # Process a specific task from the queue - # - def process_task(task) - begin - if(task.timeout) - ::Timeout.timeout(task.timeout) do - task.run(self, task) - end - else - task.run(self, task) - end - rescue ::ThreadError - # Ignore these (caused by a return inside of the proc) - rescue ::Exception => e - - if(e.class == ::Timeout::Error) - elog("taskmanager: task #{task.inspect} timed out after #{task.timeout} seconds") - task.status = :timeout - task.completed = Time.now - return :drop - end - - elog("taskmanager: task triggered an exception: #{e.class} #{e}") - elog("taskmanager: task proc: #{task.proc.inspect} ") - elog("taskmanager: task Call stack: \n#{task.source.join("\n")} ") - dlog("Call stack:\n#{$@.join("\n")}") - - task.status = :dropped - task.exception = e - return :drop - - end - task.status = :done - task.completed = Time.now - return :done - end - - def log_error(msg) - elog(msg, 'core') - end - - def log_debug(msg) - dlog(msg, 'core') - end - -end -end - diff --git a/spec/lib/msf/core/task_manager_spec.rb b/spec/lib/msf/core/task_manager_spec.rb deleted file mode 100644 index 3271df1741..0000000000 --- a/spec/lib/msf/core/task_manager_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding:binary -*- - -require 'msf/core' -require 'msf/core/task_manager' - -describe Msf::TaskManager do - - let(:framework) do - Msf::Framework.new - end - - let(:tm) do - Msf::TaskManager.new(framework) - end - - it "should have attributes" do - tm.should respond_to("processing") - tm.should respond_to("queue") - tm.should respond_to("thread") - tm.should respond_to("framework") - tm.should respond_to("processing=") - tm.should respond_to("queue=") - tm.should respond_to("thread=") - tm.should respond_to("framework=") - end - - it "should initialize with an empty queue" do - tm.queue.length.should == 0 - tm.backlog.should == 0 - tm.backlog.should == tm.queue.length - end - - it "should add items to the queue and process them" do - tm.queue_proc(Proc.new{ }) - tm.backlog.should == 1 - t = Msf::TaskManager::Task.new(Proc.new { }) - tm.queue_task(t) - tm.backlog.should == 2 - tm.start - t.wait - tm.backlog.should == 0 - end - - it "should add items to the queue and flush them" do - tm.queue_proc(Proc.new{ }) - tm.backlog.should == 1 - tm.queue_proc(Proc.new{ }) - tm.backlog.should == 2 - tm.flush - tm.backlog.should == 0 - end - - it "should start and stop" do - t = Msf::TaskManager::Task.new(Proc.new { }) - tm.queue_task(t) - tm.backlog.should == 1 - tm.start - t.wait - tm.backlog.should == 0 - tm.stop - 1.upto 100 do |cnt| - tm.queue_proc(Proc.new{ }) - tm.backlog.should == cnt - end - t = Msf::TaskManager::Task.new(Proc.new { }) - tm.queue_task(t) - tm.start - t.wait - tm.backlog.should == 0 - end - - it "should handle task timeouts" do - t = Msf::TaskManager::Task.new(Proc.new { sleep(30) }) - t.timeout = 0.1 - - tm.start - tm.queue_task(t) - t.wait - - t.status.should == :timeout - t.duration.should <= 5.0 - end - - it "should handle task exceptions" do - t = Msf::TaskManager::Task.new(Proc.new { asdf1234() }) - tm.start - tm.queue_task(t) - t.wait - t.status.should == :dropped - t.exception.class.should == ::NoMethodError - - t = Msf::TaskManager::Task.new(Proc.new { eval "'" }) - tm.queue_task(t) - t.wait - t.status.should == :dropped - t.exception.should be_a ::SyntaxError - end -end -