Class: DeepTest::Warlock
- Inherits:
-
Object
- Object
- DeepTest::Warlock
- Defined in:
- lib/deep_test/warlock.rb
Instance Method Summary collapse
- #any_running? ⇒ Boolean
- #close_open_network_connections ⇒ Object
- #demon_count ⇒ Object
- #exit_when_none_running ⇒ Object
-
#initialize(options) ⇒ Warlock
constructor
A new instance of Warlock.
-
#running?(pid) ⇒ Boolean
stolen from daemons.
- #start(name, demon, *demon_args) ⇒ Object
- #stop_demons ⇒ Object
- #wait_for_all_to_finish ⇒ Object
Constructor Details
#initialize(options) ⇒ Warlock
Returns a new instance of Warlock.
3 4 5 6 7 8 |
# File 'lib/deep_test/warlock.rb', line 3 def initialize() @options = @demons_semaphore = Mutex.new @demons = [] @reapers = [] end |
Instance Method Details
#any_running? ⇒ Boolean
98 99 100 101 102 |
# File 'lib/deep_test/warlock.rb', line 98 def any_running? @demons_semaphore.synchronize do @demons.any? {|name, pid| running?(pid)} end end |
#close_open_network_connections ⇒ Object
46 47 48 49 50 51 52 53 |
# File 'lib/deep_test/warlock.rb', line 46 def close_open_network_connections ObjectSpace.each_object(BasicSocket) do |sock| begin sock.close rescue IOError end end end |
#demon_count ⇒ Object
55 56 57 58 59 |
# File 'lib/deep_test/warlock.rb', line 55 def demon_count @demons_semaphore.synchronize do @demons.size end end |
#exit_when_none_running ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/deep_test/warlock.rb', line 82 def exit_when_none_running Thread.new do wait_for_all_to_finish DeepTest.logger.debug { "exiting #{Process.pid} with all demons finished" } exit(0) end end |
#running?(pid) ⇒ Boolean
stolen from daemons
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/deep_test/warlock.rb', line 105 def running?(pid) # Check if process is in existence # The simplest way to do this is to send signal '0' # (which is a single system call) that doesn't actually # send a signal begin Process.kill(0, pid) return true rescue Errno::ESRCH return false rescue ::Exception # for example on EPERM (process exists but does not belong to us) return true #rescue Errno::EPERM # return false end end |
#start(name, demon, *demon_args) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/deep_test/warlock.rb', line 10 def start(name, demon, *demon_args) # Not synchronizing for the fork seems to cause # random errors (Bus Error, Segfault, and GC non-object) # in Beachhead processes. # begin pid = nil @demons_semaphore.synchronize do pid = fork do # Fork leaves the semaphore locked and we'll never make it # to end of synchronize block. # # The Ruby 1.8.6 C mutex implementation automatically treats # a mutex locked by a dead thread as unlocked and will raise # an error if we try to unlock it from this thread. # @demons_semaphore.unlock if @demons_semaphore.locked? close_open_network_connections demon.forked name, @options, demon_args exit end raise "fatal: fork returned nil" if pid.nil? add_demon name, pid end launch_reaper_thread name, pid rescue => e puts "exception starting #{name}: #{e}" puts "\t" + e.backtrace.join("\n\t") end end |
#stop_demons ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/deep_test/warlock.rb', line 61 def stop_demons DeepTest.logger.debug { "stopping all demons" } receivers = @demons_semaphore.synchronize do @demons.reverse end receivers.reverse.each do |demon| name, pid = demon if running?(pid) DeepTest.logger.debug { "Sending SIGTERM to #{name}, #{pid}" } Process.kill("TERM", pid) end end DeepTest.logger.debug { "Warlock: Stopped all receivers" } DeepTest.logger.debug { "waiting for reapers" } @reapers.each {|r| r.join} DeepTest.logger.debug { "Warlock: done reaping processes" } end |
#wait_for_all_to_finish ⇒ Object
90 91 92 93 94 95 96 |
# File 'lib/deep_test/warlock.rb', line 90 def wait_for_all_to_finish loop do Thread.pass return unless any_running? sleep(0.01) end end |