Class: Msf::ThreadManager
- Inherits:
-
Array
- Object
- Array
- Msf::ThreadManager
- Includes:
- Framework::Offspring
- Defined in:
- lib/msf/core/thread_manager.rb
Overview
This class manages the threads spawned by the framework object, this provides some additional features over standard ruby threads.
Instance Attribute Summary collapse
-
#monitor ⇒ Object
Returns the value of attribute monitor.
Attributes included from Framework::Offspring
Instance Method Summary collapse
-
#initialize(framework) ⇒ ThreadManager
constructor
Initializes the thread manager.
-
#kill(idx) ⇒ Object
Kills a thread by index.
-
#register(t, name, crit) ⇒ Object
Registers an existing thread.
-
#spawn(name, crit, *args, &block) ⇒ Object
Spawns a new thread.
-
#spawn_monitor ⇒ Object
Spawns a monitor thread for removing dead threads.
-
#update(ut, name, crit) ⇒ Object
Updates an existing thread.
Constructor Details
#initialize(framework) ⇒ ThreadManager
Initializes the thread manager.
55 56 57 58 59 60 61 62 63 64 |
# File 'lib/msf/core/thread_manager.rb', line 55 def initialize(framework) self.framework = framework self.monitor = spawn_monitor # XXX: Preserve Ruby < 2.5 thread exception reporting behavior # https://ruby-doc.org/core-2.5.0/Thread.html#method-c-report_on_exception if Thread.method_defined?(:report_on_exception=) Thread.report_on_exception = false end end |
Instance Attribute Details
#monitor ⇒ Object
Returns the value of attribute monitor.
50 51 52 |
# File 'lib/msf/core/thread_manager.rb', line 50 def monitor @monitor end |
Instance Method Details
#kill(idx) ⇒ Object
Kills a thread by index
185 186 187 |
# File 'lib/msf/core/thread_manager.rb', line 185 def kill(idx) self[idx].kill rescue false end |
#register(t, name, crit) ⇒ Object
Registers an existing thread
149 150 151 152 153 154 155 156 |
# File 'lib/msf/core/thread_manager.rb', line 149 def register(t, name, crit) t[:tm_name] = name t[:tm_crit] = crit t[:tm_call] = caller t[:tm_time] = Time.now self << t t end |
#spawn(name, crit, *args, &block) ⇒ Object
Spawns a new thread
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/msf/core/thread_manager.rb', line 94 def spawn(name, crit, *args, &block) t = nil 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 ::Thread.current[:tm_time] = Time.now begin argv.shift.call(*argv) rescue ::Exception => e elog( "Thread Exception: #{::Thread.current[:tm_name]} critical=#{::Thread.current[:tm_crit]} " \ " source:\n" \ " #{::Thread.current[:tm_call].join "\n "}", error: e ) raise e ensure if framework.db && framework.db.active && framework.db.is_local? # NOTE: despite the Deprecation Warning's advice, this should *NOT* # be ApplicationRecord.connection.close which causes unrelated # threads to raise ActiveRecord::StatementInvalid exceptions at # some point in the future, presumably due to the pool manager # believing that the connection is still usable and handing it out # to another thread. ::ApplicationRecord.connection_pool.release_connection end 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 # Calling spawn without a block means we cannot force a database # connection release when the thread completes, so doing so can # potentially use up all database resources and starve all subsequent # threads that make use of the database. Log a warning so we can track # down this kind of usage. dlog("Thread spawned without a block!") dlog("Call stack: \n#{::Thread.current[:tm_call].join("\n")}") end end self << t t end |
#spawn_monitor ⇒ Object
Spawns a monitor thread for removing dead threads
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/msf/core/thread_manager.rb', line 69 def spawn_monitor ::Thread.new do begin ::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) end rescue ::Exception => e elog("Thread Monitor Exception | Source: #{self[:tm_call].inspect}", error: e) end end end |
#update(ut, name, crit) ⇒ Object
Updates an existing thread
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/msf/core/thread_manager.rb', line 161 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 t = self[ti] if not t raise RuntimeError, "Thread not found" end t[:tm_name] = name t[:tm_crit] = crit t end |