I'm using Timeout::timeout(1)
for a process that takes longer than 1 second, though it only occasionally triggers a timeout. When it does, rescue
captures it in different ways each time. Here's a sample of my code:
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
Here are the three scenarios I encounter with the same input:
- Process runs to completion and takes longer than 60 seconds
- Process times out and hangs, printing only
execution expired
indevelopment.log
- Process times out, is rescued properly, prints
"Timeout"
indevelopment.log
, and returnsnil
Why is this so inconsistent?
UPDATE
After reducing the timeout to 0.0001s, the process is timing out consistently and as expected. It seems that the open(file_url)
block was opening faster than 1 second, and despite everything within the block taking more than 1 second, the Timeout
was only triggered if the opening itself took longer than 1 second.
This however did not explain the execution expired
exception. To test this, I moved the Timeout::timeout(0.0001)
to within the open
block. The code looks like the following:
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
Now, I'm consistently receiving the output EXCEPTION 2 - execution expired
. Why is it that the Timeout::Error
is not being triggered here?