1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #29034 from peterjm/handle_loops_in_exception_handling

Handle loops in the cause chain in Rescuable#rescue_with_handler
This commit is contained in:
Rafael França 2017-05-11 17:45:03 -07:00 committed by GitHub
commit f96c14096c
2 changed files with 41 additions and 3 deletions

View file

@ -84,12 +84,18 @@ module ActiveSupport
# end
#
# Returns the exception if it was handled and +nil+ if it was not.
def rescue_with_handler(exception, object: self)
def rescue_with_handler(exception, object: self, visited_exceptions: [])
visited_exceptions << exception
if handler = handler_for_rescue(exception, object: object)
handler.call exception
exception
elsif exception
rescue_with_handler(exception.cause, object: object)
if visited_exceptions.include?(exception.cause)
nil
else
rescue_with_handler(exception.cause, object: object, visited_exceptions: visited_exceptions)
end
end
end

View file

@ -43,7 +43,9 @@ class Stargate
def dispatch(method)
send(method)
rescue Exception => e
rescue_with_handler(e)
unless rescue_with_handler(e)
@result = "unhandled"
end
end
def attack
@ -58,6 +60,26 @@ class Stargate
raise MadRonon.new("dex")
end
def crash
raise "unhandled RuntimeError"
end
def looped_crash
ex1 = StandardError.new("error 1")
ex2 = StandardError.new("error 2")
begin
begin
raise ex1
rescue
# sets the cause on ex2 to be ex1
raise ex2
end
rescue
# sets the cause on ex1 to be ex2
raise ex1
end
end
def fall_back_to_cause
# This exception is the cause and has a handler.
ronanize
@ -139,4 +161,14 @@ class RescuableTest < ActiveSupport::TestCase
@stargate.dispatch :fall_back_to_cause
assert_equal "dex", @stargate.result
end
def test_unhandled_exceptions
@stargate.dispatch(:crash)
assert_equal "unhandled", @stargate.result
end
def test_rescue_handles_loops_in_exception_cause_chain
@stargate.dispatch :looped_crash
assert_equal "unhandled", @stargate.result
end
end