2010-06-30 304 views
10

我使用BrB分擔Ruby 1.9中的各種工作進程一個數據源,我和處理#叉叉像跟蹤死鎖以下:在紅寶石

Thread.abort_on_exception = true 

fork do 
    puts "Initializing data source process... (PID: #{Process.pid})" 
    data = DataSource.new(files) 

    BrB::Service.start_service(:object => data, :verbose => false, :host => host, :port => port) 
    EM.reactor_thread.join 
end

工人們正在叉形如下:

8.times do |t| 
    fork do 
    data = BrB::Tunnel.create(nil, "brb://#{host}:#{port}", :verbose => false) 

    puts "Launching #{threads_num} worker threads... (PID: #{Process.pid})"  

    threads = [] 
    threads_num.times { |i| 
     threads << Thread.new { 
     while true 
      begin 
      worker = Worker.new(data, config) 

      rescue OutOfTargetsError 
      break 

      rescue Exception => e 
      puts "An unexpected exception was caught: #{e.class} => #{e}" 
      sleep 5 

      end 
     end 
     } 
    } 
    threads.each { |t| t.join } 

    data.stop_service 
    EM.stop 
    end 
end

這工作非常完美,但約10分鐘的運行後,我得到了以下錯誤:

bootstrap.rb:47:in `join': deadlock detected (fatal) 
     from bootstrap.rb:47:in `block in ' 
     from bootstrap.rb:39:in `fork' 
     from bootstrap.rb:39:in `'

現在這個錯誤並沒有告訴我有關死鎖實際發生的地方,它只是指向EventMachine線程上的連接。

如何追溯程序鎖定的位置?

+0

你試過把'Thread.exit'塊結束之前? – glebm 2012-12-09 07:25:21

回答

5

它鎖定在父線程中的連接,該信息是準確的。 要追蹤它鎖定在子線程中的位置,請嘗試將線程的工作包裝在timeout block中。您需要臨時移除超時異常的全面救援以提升。

當前父線程嘗試按順序連接所有線程,直到每個線程完成爲止。但是每個線程只會加入OutOfTargetsError。通過使用短暫的線程並將while循環移動到父項中,可以避免死鎖。沒有保證,但也許這樣?

8.times do |t| 
    fork do 
    running = true 
    Signal.trap("INT") do 
     puts "Interrupt signal received, waiting for threads to finish..." 
     running = false 
    end 

    data = BrB::Tunnel.create(nil, "brb://#{host}:#{port}", :verbose => false) 

    puts "Launching max #{threads_num} worker threads... (PID: #{Process.pid})"  

    threads = [] 
    while running 
     # Start new threads until we have threads_num running 
     until threads.length >= threads_num do 
     threads << Thread.new { 
      begin 
      worker = Worker.new(data, config) 
      rescue OutOfTargetsError 
      rescue Exception => e 
      puts "An unexpected exception was caught: #{e.class} => #{e}" 
      sleep 5 
      end 
     } 
     end 

     # Make sure the parent process doesn't spin too much 
     sleep 1 

     # Join finished threads 
     finished_threads = threads.reject &:status 
     threads -= finished_threads 
     finished_threads.each &:join 
    end 

    data.stop_service 
    EM.stop 
    end 
end 
+0

嘿,夥計,這種方法的運氣? – captainpete 2011-05-05 22:58:13

2

我有同樣的問題,通過使用此代碼段soved它。

# Wait for all threads (other than the current thread and 
# main thread) to stop running. 
# Assumes that no new threads are started while waiting 
def join_all 
    main  = Thread.main  # The main thread 
    current = Thread.current # The current thread 
    all  = Thread.list  # All threads still running 
    # Now call join on each thread 
    all.each{|t| t.join unless t == current or t == main } 
end 

來源:Ruby編程語言,奧賴利(2008)