Bug #18375
closedTimeout.timeout(sec, klass: MyExceptionClass) can not retry correctly.
Description
Following is a example for describe this issue.
class DelayError < Exception
end
Timeout.timeout(2, DelayError) do |arg|
puts 'start'
sleep 10
rescue DelayError
puts '*'*10
retry
end
Will output
start
**********
start
What i expected is:
start
**********
start
**********
start
**********
...
Basically, what i expected equivalent is:
begin
Timeout.timeout(2) do |arg|
puts 'start'
sleep 10
end
rescue TimeoutError
puts '*'*10
retry
end
Updated by jeremyevans0 (Jeremy Evans) almost 3 years ago
- Status changed from Open to Rejected
I don't think this is a bug, and I don't think timeout can work with your proposed code. There's no way the block-level rescue
can work the way you want, since what you want requires the timeout
method be called again.
This code:
Timeout.timeout(2, DelayError) do |arg|
puts 'start'
sleep 10
rescue DelayError
puts '*'*10
retry
end
is short for:
Timeout.timeout(2, DelayError) do |arg|
begin
puts 'start'
sleep 10
rescue DelayError
puts '*'*10
retry
end
end
It's not short for:
begin
Timeout.timeout(2, DelayError) do |arg|
puts 'start'
sleep 10
end
rescue DelayError
puts '*'*10
retry
end
Even if it were short for that, that code doesn't work the way you want either (looks like an infinite loop). You probably want something like:
deadline = Time.now + 10
begin
Timeout.timeout(2, DelayError) do |arg|
puts 'start'
sleep(deadline - Time.now)
end
rescue DelayError
puts '*'*10
retry
end
Updated by zw963 (Wei Zheng) almost 3 years ago
jeremyevans0 (Jeremy Evans) wrote in #note-2:
I don't think this is a bug, and I don't think timeout can work with your proposed code. There's no way the block-level
rescue
can work the way you want, since what you want requires thetimeout
method be called again.This code:
Timeout.timeout(2, DelayError) do |arg| puts 'start' sleep 10 rescue DelayError puts '*'*10 retry end
is short for:
Timeout.timeout(2, DelayError) do |arg| begin puts 'start' sleep 10 rescue DelayError puts '*'*10 retry end end
It's not short for:
begin Timeout.timeout(2, DelayError) do |arg| puts 'start' sleep 10 end rescue DelayError puts '*'*10 retry end
Even if it were short for that, that code doesn't work the way you want either (looks like an infinite loop). You probably want something like:
deadline = Time.now + 10 begin Timeout.timeout(2, DelayError) do |arg| puts 'start' sleep(deadline - Time.now) end rescue DelayError puts '*'*10 retry end
In fact, if consider following code more useful than the actually form.
begin
Timeout.timeout(2, DelayError) do |arg|
puts 'start'
sleep 10
end
rescue DelayError
puts '*'*10
retry
end
Perhaps, we should do some specially process for Timeout.timeout
rescue block.