Skip to content

Instantly share code, notes, and snippets.

@mitio
Last active December 9, 2018 08:57
Show Gist options
  • Save mitio/6194e94a8a062c6cbead77fecc7f6ed4 to your computer and use it in GitHub Desktop.
Save mitio/6194e94a8a062c6cbead77fecc7f6ed4 to your computer and use it in GitHub Desktop.

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment