0

Timeout::timeout(1)たまにタイムアウトが発生するだけですが、1秒以上かかるプロセスに使用しています。そのときは、rescue毎回さまざまな方法でキャプチャします。これが私のコードのサンプルです:

require 'timeout'
...
begin
  status = Timeout::timeout(1) {
    open(file_url) do |foo|
      feed = RSS::Parser.parse(foo)
      some_method_call(arg1, arg2)
      #other stuff
    end
  }
rescue Timeout::Error
  Rails.logger.debug "Timeout"
  return nil
rescue Exception => ex
  Rails.logger.debug "EXCEPTION - #{ex.message}"
  return nil
end

同じ入力で遭遇する 3 つのシナリオを次に示します。

  • プロセスが完了するまで実行され、60 秒以上かかる
  • プロセスがタイムアウトしてハングし、印刷execution expiredのみdevelopment.log
  • プロセスがタイムアウトし、適切にレスキューされ、 に出力"Timeout"されdevelopment.log、返されますnil

なぜこれほど一貫性がないのでしょうか。

アップデート

タイムアウトを 0.0001 秒に減らした後、プロセスは一貫して期待どおりにタイムアウトします。ブロックは 1 秒よりも速く開いていたようで、open(file_url)ブロック内のすべての処理に 1 秒以上かかったにもかかわらず、ブロックを開くのに 1 秒以上Timeoutかかった場合にのみ、ブロックがトリガーされました。

execution expiredただし、これは例外を説明しませんでした。これをテストするために、 to をブロックTimeout::timeout(0.0001)内に移動しました。openコードは次のようになります。

require 'timeout'
...
begin
  open(file_url) do |foo|
    status = Timeout::timeout(0.0001) do
      begin
        feed = RSS::Parser.parse(foo)
        some_method_call(arg1, arg2)
        #other stuff
      rescue Timeout::Error
        Rails.logger.debug "Timeout 2"
      rescue Exception => ex
        Rails.logger.debug "EXCEPTION 2 - #{ex.message}"
      end
    end
  end
rescue Timeout::Error
  Rails.logger.debug "Timeout"
  return nil
rescue Exception => ex
  Rails.logger.debug "EXCEPTION - #{ex.message}"
  return nil
end

今、私は一貫して output を受け取っていますEXCEPTION 2 - execution expiredTimeout::Errorここで がトリガーされないのはなぜですか?

4

2 に答える 2

1

あなたの内面

rescue Exception => ex
  Rails.logger.debug "EXCEPTION 2 - #{ex.message}"
end

アウターtimeoutブロックの浮き上がりを抑えTimeout::Errorます。

そのステートメントを削除するとrescue、うまくいくはずです。

本当に例外をキャッチする必要がある場合は、次のものに置き換えます。

rescue StandardError => ex
  Rails.logger.debug "EXCEPTION 2 - #{ex.message}"
end
于 2012-07-11T19:43:36.733 に答える
0

内部的に (Timeout ブロック内で) Timeout は Timeout::Error を使用しません。もしそうなら、あらゆる種類の救助がそれを捕まえるでしょう、そしてあなたはそれを望んでいません. したがって、新しい例外を作成してそれを使用することで、通常のエラー処理をすべて吹き飛ばし、実際にコードの実行を停止させることができます。

ruby200/lib/ruby/2.0.0 の timeout.rb コードを確認してください。それはかなり短く、かなり有益です。

特に、Timeout::timeout の 2 番目のパラメーターとして独自の Exception を渡すことができ、Timeout はそれを使用します。したがって、必要に応じて、コード内でキャッチできます。

Logger は現在、書き込み中に発生するすべての例外をトラップし、再発生させないことに注意してください。バグレポートを提出しました。

于 2013-11-16T04:31:43.640 に答える