Given something like this
def infinite
puts Time.now
rescue => err
puts err.message
ensure
infinite
end
When you run this in console/rake and hit ctrl-c - nothing happens. How do you escape this with CTRL-C?
CodePudding user response:
I'm not sure if this is the proper solution but this worked for me:
def infinite
puts Time.now
rescue SystemExit, Interrupt
@skip_ensure = true
puts 'SystemExist/Interrupt'
rescue => err
puts err.message
ensure
infinite unless @skip_ensure
end
CodePudding user response:
Use catch
instead which is an alternative control flow.
catch executes its block. If throw is not called, the block executes normally, and catch returns the value of the last expression evaluated.
Ruby searches up its stack for a catch block whose tag has the same object_id as the throw (symbols are almost always used as the have the same object_id). When found, the block stops executing and returns val (or nil if no second argument was given to throw).
def infinate
catch(:done) do
begin
infinite
rescue SystemExit, Interrupt => e
puts e.message
throw :done
end
end
end
Using ensure
with a condition like that is semantically wrong as the whole point of ensure is to run code that always should be run.
CodePudding user response:
Using rescue
to create an infinite loop via recursion seem overly complicated and could cause a SystemStackError
later on.
Why not use an actual loop
:
def infinite
loop do
begin
puts Time.now
rescue => err
puts err.message
end
end
end
With the above, Ctrl-C works just fine, because rescue
without an explicit exception class will only handle StandardErrors.