Class: Arachni::BrowserCluster::Worker
- Inherits:
-
Arachni::Browser
- Object
- Arachni::Browser
- Arachni::BrowserCluster::Worker
- Defined in:
- lib/arachni/browser_cluster/worker.rb
Overview
Overrides some Arachni::Browser methods to make multiple browsers play well with each other when they're part of a Arachni::BrowserCluster.
Constant Summary collapse
- TRIES =
How many times to retry timed-out jobs.
6
Constants inherited from Arachni::Browser
Arachni::Browser::ASSET_EXTENSIONS, Arachni::Browser::ASSET_EXTRACTORS, Arachni::Browser::BROWSER_SPAWN_TIMEOUT, Arachni::Browser::ELEMENT_APPEARANCE_TIMEOUT, Arachni::Browser::INPUT_EVENTS, Arachni::Browser::INPUT_EVENTS_TO_FORCE
Instance Attribute Summary collapse
-
#job ⇒ Job
readonly
Currently assigned job.
- #master ⇒ BrowserCluster readonly
- #max_time_to_live ⇒ Integer
-
#time_to_live ⇒ Integer
readonly
Remaining time-to-live measured in jobs.
Attributes inherited from Arachni::Browser
#javascript, #last_url, #page_snapshots_with_sinks, #preloads, #proxy, #selenium, #transitions, #watir
Instance Method Summary collapse
- #browser_shutdown ⇒ Object
-
#distribute_event(resource, element, event) ⇒ Object
Direct the distribution to the master and let it take it from there.
-
#initialize(options = {}) ⇒ Worker
constructor
A new instance of Worker.
- #inspect ⇒ Object
-
#run_job(job) ⇒ Array<Page>
Pages which resulted from firing events, clicking JavaScript links and capturing AJAX requests.
-
#shutdown(wait = true) ⇒ Object
Shuts down the worker.
Methods inherited from Arachni::Browser
add_asset_domain, asset_domains, #capture?, #capture_snapshot, #captured_pages, #clear_buffers, #cookies, #dom_url, #each_element_with_events, executable, #explore_and_flush, #fire_event, #fire_event_js, #flush_page_snapshots_with_sinks, #flush_pages, #goto, has_executable?, #load, #load_delay, #on_fire_event, #on_new_page, #on_new_page_with_sink, #on_response, #page_snapshots, #preload, reset, #response, #skip_path?, #source, #source_with_line_numbers, #start_capture, #state, #stop_capture, #to_page, #trigger_event, #trigger_events, #update_cookies, #url, #wait_for_timers, #wait_till_ready
Methods included from Support::Mixins::Observable
Methods included from Utilities
#available_port, available_port_mutex, #bytes_to_kilobytes, #bytes_to_megabytes, #caller_name, #caller_path, #cookie_decode, #cookie_encode, #cookies_from_file, #cookies_from_parser, #cookies_from_response, #exception_jail, #exclude_path?, #follow_protocol?, #form_decode, #form_encode, #forms_from_parser, #forms_from_response, #full_and_absolute_url?, #generate_token, #get_path, #hms_to_seconds, #html_decode, #html_encode, #include_path?, #links_from_parser, #links_from_response, #normalize_url, #page_from_response, #page_from_url, #parse_set_cookie, #path_in_domain?, #path_too_deep?, #port_available?, #rand_port, #random_seed, #redundant_path?, #regexp_array_match, #remove_constants, #request_parse_body, #seconds_to_hms, #skip_page?, #skip_path?, #skip_resource?, #skip_response?, #to_absolute, #uri_decode, #uri_encode, #uri_parse, #uri_parse_query, #uri_parser, #uri_rewrite
Methods included from UI::Output
#debug?, #debug_level_1?, #debug_level_2?, #debug_level_3?, #debug_level_4?, #debug_off, #debug_on, #disable_only_positives, #included, #mute, #muted?, #only_positives, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_level_1, #print_debug_level_2, #print_debug_level_3, #print_debug_level_4, #print_error, #print_error_backtrace, #print_exception, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, reset_output_options, #unmute, #verbose?, #verbose_on
Constructor Details
#initialize(options = {}) ⇒ Worker
Returns a new instance of Worker.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/arachni/browser_cluster/worker.rb', line 40 def initialize( = {} ) @master = .delete( :master ) @max_time_to_live = .delete( :max_time_to_live ) || Options.browser_cluster.worker_time_to_live @time_to_live = @max_time_to_live @done_signal = Queue.new # Don't store pages if there's a master, we'll be sending them to him # as soon as they're logged. super .merge( store_pages: false ) start_capture return if !@master start end |
Instance Attribute Details
#job ⇒ Job (readonly)
Returns Currently assigned job.
31 32 33 |
# File 'lib/arachni/browser_cluster/worker.rb', line 31 def job @job end |
#master ⇒ BrowserCluster (readonly)
27 28 29 |
# File 'lib/arachni/browser_cluster/worker.rb', line 27 def master @master end |
#max_time_to_live ⇒ Integer
34 35 36 |
# File 'lib/arachni/browser_cluster/worker.rb', line 34 def max_time_to_live @max_time_to_live end |
#time_to_live ⇒ Integer (readonly)
Returns Remaining time-to-live measured in jobs.
38 39 40 |
# File 'lib/arachni/browser_cluster/worker.rb', line 38 def time_to_live @time_to_live end |
Instance Method Details
#browser_shutdown ⇒ Object
139 |
# File 'lib/arachni/browser_cluster/worker.rb', line 139 alias :browser_shutdown :shutdown |
#distribute_event(resource, element, event) ⇒ Object
Direct the distribution to the master and let it take it from there.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/arachni/browser_cluster/worker.rb', line 122 def distribute_event( resource, element, event ) master.queue( @job.forward_as( @job.class::EventTrigger, resource: resource, element: element, event: event ), master.callback_for( @job ) ) true # Job may have been marked as done or the cluster may have been shut down. rescue BrowserCluster::Job::Error::AlreadyDone, BrowserCluster::Error::AlreadyShutdown false end |
#inspect ⇒ Object
183 184 185 186 187 188 189 190 |
# File 'lib/arachni/browser_cluster/worker.rb', line 183 def inspect s = "#<#{self.class} " s << "pid=#{@lifeline_pid} " s << "job=#{@job.inspect} " s << "last-url=#{@last_url.inspect} " s << "transitions=#{@transitions.size}" s << '>' end |
#run_job(job) ⇒ Array<Page>
Returns Pages which resulted from firing events, clicking JavaScript links and capturing AJAX requests.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/arachni/browser_cluster/worker.rb', line 66 def run_job( job ) @job = job print_debug "Started: #{@job}" # PhantomJS may have crashed (it happens sometimes) so make sure that # we've got a live one before running the job. # If we can't respawn, then bail out. return if browser_respawn_if_necessary.nil? time = Time.now begin Timeout.timeout Options.browser_cluster.job_timeout do @job.configure_and_run( self ) end @job.time = Time.now - time rescue Selenium::WebDriver::Error::WebDriverError, Watir::Exception::Error => e print_debug "WebDriver error while processing job: #{@job}" print_debug_exception e # This can be thrown by a Selenium call somewhere down the line, # catch it here and retry the entire job. rescue Timeout::Error => e @job.timed_out!( Time.now - time ) print_bad "Job timed-out: #{@job}" print_debug_exception e master.increment_time_out_count end decrease_time_to_live # Something went horribly wrong, cleanup. rescue => e print_error "Error while processing job: #{@job}" print_exception e browser_respawn ensure print_debug "Finished: #{@job}" @job = nil reset master.job_done job end |
#shutdown(wait = true) ⇒ Object
If there is a running job it will wait for it to finish.
Shuts down the worker.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/arachni/browser_cluster/worker.rb', line 143 def shutdown( wait = true ) return if @shutdown @shutdown = true print_debug "Shutting down (wait: #{wait}) ..." # Keep checking to see if any of the 'done' criteria are true. kill_check = Thread.new do while wait && @job print_debug_level_2 "Waiting for job to complete: #{job}" sleep 0.1 end print_debug_level_2 'Signaling done.' @done_signal << nil end print_debug_level_2 'Waiting for done signal...' # If we've got a job running wait for it to finish before closing the # browser otherwise we'll get Selenium errors and zombie processes. @done_signal.pop print_debug_level_2 '...done.' print_debug_level_2 'Waiting for kill check...' kill_check.join print_debug_level_2 '...done.' if @consumer print_debug_level_2 'Killing consumer thread...' @consumer.kill print_debug_level_2 '...done.' end print_debug_level_2 'Calling parent shutdown...' browser_shutdown print_debug_level_2 '...done.' print_debug '...shutdown complete.' end |