Class: Tork::Master
Constant Summary collapse
- MAX_CONCURRENT_WORKERS =
detect the number of CPUs available in the system stackoverflow.com/questions/891537#6420817
[ 'fgrep -c processor /proc/cpuinfo', # Linux 'sysctl -n hw.ncpu', # BSD 'hwprefs cpu_count', # Darwin 9 'hwprefs thread_count', # Darwin 10 ]. map {|cmd| `#{cmd} 2>/dev/null`.to_i }.push(1).max
Instance Method Summary collapse
-
#initialize ⇒ Master
constructor
A new instance of Master.
- #loop ⇒ Object
- #stop(signal = :SIGTERM) ⇒ Object
- #test(test_file, line_numbers) ⇒ Object
Methods inherited from Server
Constructor Details
#initialize ⇒ Master
Returns a new instance of Master.
17 18 19 20 21 22 23 24 |
# File 'lib/tork/master.rb', line 17 def initialize super Tork.config :master send @clients, [:boot] @worker_number_pool = (0 ... MAX_CONCURRENT_WORKERS).to_a @command_by_worker_pid = {} end |
Instance Method Details
#loop ⇒ Object
26 27 28 29 30 |
# File 'lib/tork/master.rb', line 26 def loop super ensure stop :SIGKILL end |
#stop(signal = :SIGTERM) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/tork/master.rb', line 79 def stop signal=:SIGTERM # the reaping threads registered above will reap these killed workers Process.kill signal, *@command_by_worker_pid.keys.map {|pid| -pid } rescue ArgumentError, SystemCallError # some workers might have already exited before we sent them the signal end |
#test(test_file, line_numbers) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/tork/master.rb', line 32 def test test_file, line_numbers # throttle forking rate to meet the maximum concurrent workers limit sleep 1 until @command_by_worker_pid.size <= @worker_number_pool.size $tork_test_file = test_file $tork_line_numbers = line_numbers $tork_log_file = $tork_test_file + '.log' $tork_worker_number = @worker_number_pool.shift Tork.config :onfork worker_pid = fork do # make the process title Test::Unit friendly and ps(1) searchable $0 = "tork-worker[#{$tork_worker_number}] #{$tork_test_file}" # detach worker process from master process' group for kill -pgrp Process.setsid # detach worker process from master process' standard input stream STDIN.reopen IO.pipe.first # capture test output in log file because tests are run in parallel # which makes it difficult to understand interleaved output thereof STDERR.reopen(STDOUT.reopen($tork_log_file, 'w')).sync = true Tork.config :worker # after loading the user's test file, the at_exit() hook of the user's # testing framework will take care of running the tests and reflecting # any failures in the worker process' exit status, which will then be # handled by the reaping thread registered in the master process (below) Kernel.load $tork_test_file if $tork_test_file.end_with? '.rb' end @command.push $tork_log_file, $tork_worker_number @command_by_worker_pid[worker_pid] = @command send @clients, @command # wait for the worker to finish and report its status to the client Thread.new(worker_pid) do |pid| # the reaping thread status = Process.wait2(pid).last command = @command_by_worker_pid.delete(pid) @worker_number_pool.push command.last command[0] = status.success? && :pass || :fail send @clients, command.push(status.to_i, status.inspect) end end |