Ensure will always catch Timeout::Error
but nested rescue
clauses will not, unless a custom exception class is used as per the docs:
The exception thrown to terminate the given block cannot be rescued inside the block unless klass is given explicitly.
No rescue
:
irb(main):001:0> Timeout.timeout 1 do
irb(main):002:1* puts 'sleeping'
irb(main):003:1> sleep 2
irb(main):004:1> ensure
irb(main):005:1* puts 'entered into ensure'
irb(main):006:1> end
sleeping
entered into ensure
Traceback (most recent call last):
5: from /Users/dimitar/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
4: from (irb):1
3: from /Users/dimitar/.rbenv/versions/2.5.1/lib/ruby/2.5.0/timeout.rb:108:in `timeout'
2: from (irb):3:in `block in irb_binding'
1: from (irb):3:in `sleep'
Timeout::Error (execution expired)
irb(main):007:0> begin
irb(main):008:1> puts 'nested timeout block'
irb(main):009:1> Timeout.timeout 1 do
irb(main):010:2* puts 'starting job...'
irb(main):011:2> sleep 2
irb(main):012:2> ensure
irb(main):013:2* puts 'nested ensure'
irb(main):014:2> end
irb(main):015:1> ensure
irb(main):016:1* puts 'outer ensure'
irb(main):017:1> end
nested timeout block
starting job...
nested ensure
outer ensure
Traceback (most recent call last):
5: from /Users/dimitar/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
4: from (irb):9
3: from /Users/dimitar/.rbenv/versions/2.5.1/lib/ruby/2.5.0/timeout.rb:108:in `timeout'
2: from (irb):11:in `block in irb_binding'
1: from (irb):11:in `sleep'
Timeout::Error (execution expired)
With rescue
:
irb(main):018:0>
irb(main):019:0> Timeout.timeout 1 do
irb(main):020:1* puts 'sleeping'
irb(main):021:1> sleep 2
irb(main):022:1> rescue
irb(main):023:1> puts 'nested rescue does not catch Timeout::Error by default'
irb(main):024:1> ensure
irb(main):025:1* puts 'entered into ensure'
irb(main):026:1> end
sleeping
entered into ensure
Traceback (most recent call last):
5: from /Users/dimitar/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
4: from (irb):19
3: from /Users/dimitar/.rbenv/versions/2.5.1/lib/ruby/2.5.0/timeout.rb:108:in `timeout'
2: from (irb):21:in `block in irb_binding'
1: from (irb):21:in `sleep'
Timeout::Error (execution expired)
irb(main):027:0> begin
irb(main):028:1> puts 'nested timeout block'
irb(main):029:1> Timeout.timeout 1 do
irb(main):030:2* puts 'starting job...'
irb(main):031:2> sleep 2
irb(main):032:2> rescue
irb(main):033:2> puts 'nested rescue does not catch Timeout::Error by default'
irb(main):034:2> ensure
irb(main):035:2* puts 'nested ensure'
irb(main):036:2> end
irb(main):037:1> rescue
irb(main):038:1> puts 'outer rescue catches Timeout::Error'
irb(main):039:1> ensure
irb(main):040:1* puts 'outer ensure'
irb(main):041:1> end
nested timeout block
starting job...
nested ensure
outer rescue catches Timeout::Error
outer ensure
=> nil
irb(main):042:0>