Consider this begin-rescue-ensure block:
attempts=0
begin
make_service_call()
rescue Exception
retry unless attempts>2
exit -1
ensure
attemps += 1
The ensure
section is executed when leaving the begin
statement (by any means) but when you retry
, you're just moving around inside the statement so the ensure section will not be executed.
Try this version of your example to get a better idea of what's going on:
attempts = 0
begin
make_service_call()
rescue Exception
attempts += 1
retry unless attempts > 2
exit -1
ensure
puts "ensure! #{attempts}"
end
ensure
code is executed once, just before the code block exits and it will be called at that time.
But because of the unless attempts>2
condition, and the fact that ensure
will only be called "just before the code exits" (e.g. due to exit -1
) the attempts += 1
will not be executed, and so there is an infinite loop.
ensure
is like __finally
in C++ : you could catch
the exception and then use a goto
: but finally
will not be called until the function is actually about to exit.