2010-11-12 06:19:49 +00:00
|
|
|
require 'msf/core/plugin'
|
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class manages the threads spawned by the framework object, this provides some additional
|
|
|
|
# features over standard ruby threads.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class ThreadManager < Array
|
|
|
|
|
|
|
|
include Framework::Offspring
|
|
|
|
|
|
|
|
attr_accessor :monitor
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
#
|
|
|
|
# Initializes the thread manager.
|
|
|
|
#
|
|
|
|
def initialize(framework)
|
|
|
|
self.framework = framework
|
|
|
|
self.monitor = spawn_monitor
|
|
|
|
end
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
#
|
|
|
|
# Spawns a monitor thread for removing dead threads
|
|
|
|
#
|
|
|
|
def spawn_monitor
|
|
|
|
::Thread.new do
|
|
|
|
begin
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
::Thread.current[:tm_name] = "Thread Monitor"
|
|
|
|
::Thread.current[:tm_crit] = true
|
|
|
|
|
|
|
|
while true
|
|
|
|
::IO.select(nil, nil, nil, 1.0)
|
|
|
|
self.each_index do |i|
|
|
|
|
state = self[i].alive? rescue false
|
|
|
|
self[i] = nil if not state
|
|
|
|
end
|
|
|
|
self.delete(nil)
|
2011-11-20 01:10:08 +00:00
|
|
|
end
|
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
rescue ::Exception => e
|
|
|
|
elog("thread monitor: #{e} #{e.backtrace} source:#{self[:tm_call].inspect}")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Spawns a new thread
|
|
|
|
#
|
|
|
|
def spawn(name, crit, *args, &block)
|
|
|
|
t = nil
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
if block
|
|
|
|
t = ::Thread.new(name, crit, caller, block, *args) do |*argv|
|
|
|
|
::Thread.current[:tm_name] = argv.shift.to_s
|
|
|
|
::Thread.current[:tm_crit] = argv.shift
|
|
|
|
::Thread.current[:tm_call] = argv.shift
|
2011-11-20 01:10:08 +00:00
|
|
|
::Thread.current[:tm_time] = Time.now
|
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
begin
|
|
|
|
argv.shift.call(*argv)
|
|
|
|
rescue ::Exception => e
|
2011-04-07 21:59:32 +00:00
|
|
|
elog("thread exception: #{::Thread.current[:tm_name]} critical=#{::Thread.current[:tm_crit]} error:#{e.class} #{e} source:#{::Thread.current[:tm_call].inspect}")
|
|
|
|
elog("Call Stack\n#{e.backtrace.join("\n")}")
|
2010-11-13 06:22:40 +00:00
|
|
|
raise e
|
2010-11-12 06:19:49 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
t = ::Thread.new(name, crit, caller, *args) do |*argv|
|
|
|
|
::Thread.current[:tm_name] = argv.shift
|
|
|
|
::Thread.current[:tm_crit] = argv.shift
|
|
|
|
::Thread.current[:tm_call] = argv.shift
|
|
|
|
::Thread.current[:tm_time] = Time.now
|
2011-11-20 01:10:08 +00:00
|
|
|
end
|
2010-11-12 06:19:49 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
self << t
|
|
|
|
t
|
|
|
|
end
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
#
|
|
|
|
# Registers an existing thread
|
|
|
|
#
|
|
|
|
def register(t, name, crit)
|
|
|
|
t[:tm_name] = name
|
|
|
|
t[:tm_crit] = crit
|
|
|
|
t[:tm_call] = caller
|
2011-11-20 01:10:08 +00:00
|
|
|
t[:tm_time] = Time.now
|
2010-11-12 06:19:49 +00:00
|
|
|
self << t
|
|
|
|
t
|
|
|
|
end
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 17:28:40 +00:00
|
|
|
#
|
|
|
|
# Updates an existing thread
|
|
|
|
#
|
|
|
|
def update(ut, name, crit)
|
|
|
|
ti = nil
|
|
|
|
self.each_index do |i|
|
|
|
|
tt = self[i]
|
|
|
|
next if not tt
|
|
|
|
if ut.__id__ == tt.__id__
|
|
|
|
ti = i
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 17:28:40 +00:00
|
|
|
t = self[ti]
|
|
|
|
if not t
|
|
|
|
raise RuntimeError, "Thread not found"
|
|
|
|
end
|
|
|
|
|
|
|
|
t[:tm_name] = name
|
|
|
|
t[:tm_crit] = crit
|
|
|
|
t
|
2011-11-20 01:10:08 +00:00
|
|
|
end
|
2010-11-12 17:28:40 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
#
|
|
|
|
# Kills a thread by index
|
|
|
|
#
|
|
|
|
def kill(idx)
|
|
|
|
self[idx].kill rescue false
|
|
|
|
end
|
2011-11-20 01:10:08 +00:00
|
|
|
|
2010-11-12 06:19:49 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|