こんにちは、Rubyist九州の新井です。

Railsなどを実行していると、たまにハングすることがありますが、
そのときにデバッグに苦慮することがあります。

gdbでattachして内容を確かめることもありますが、運良く情報が
簡単に得られて解決したのは1度きりで、大体の場合、
僕のスキルではgdbを使って問題解決するのは難しいようです。

たまに発生するハングアップの場合は、常時詳細なログを取って
デバッグすることも難しいですし、困ってしまいます。

そこで末尾に付属したようなコードを書いて、もしプログラムが
長期間動きっぱなしになっている場合はタイムアウトを発生させ、
そのときのbacktraceを取得できる、という方法を考えました。

しかしRailsの場合、これを組み込むのも容易ではない感じです。
どこかでExceptionをrescueしていれば終わりですし。

何か良い策はないものでしょうか?

他スレッドの内容をダンプしたり、もしくは実行中のRubyプロセスの
内容をダンプ・解析するような方法があれば、是非ご教示頂きたく存じます。

--- ここから ---

class ThreadTimeout < Exception
end

class Watchdog
  attr_accessor :timeout
  def initialize
    @timeout = 120
  end
  def run
    t = nil
    start = Time.now
    t = Thread.new {
      begin
        Thread.current[:retval] = yield
      rescue ThreadTimeout => e
        Thread.current[:timeout] = e
      rescue Exception => e
        Thread.current[:exception] = e
      end
    }
    while(t.alive?)
      if (Time.now - start) > @timeout
        t.raise(ThreadTimeout.new)
      end
    end
    if t[:timeout]
      puts t[:timeout]
      puts t[:timeout].backtrace
      return nil
    end
    raise t[:exception] if t[:exception]
    t[:retval]
  end
end

--- ここまで ---

-----
Mellowtone Inc. - life is a melody
Shunichi Arai

http://www.mellowtone.co.jp
http://asiajin.com/blog/