From a561bdb25ff51809c5de63ab7083ebf25d37cda9 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Tue, 29 Dec 2015 20:36:12 +0900 Subject: Support backtrace after method calls GitHub: fix #2902, #2917 The current implementation traverses stack to retrieve backtrace. But stack will be changed when some operations are occurred. It means that backtrace may be broken after some operations. This change (1) saves the minimum information to retrieve backtrace when exception is raised and (2) restores backtrace from the minimum information when backtrace is needed. It reduces overhead for creating backtrace Ruby objects. The space for the minimum information is reused by multiple exceptions. So memory allocation isn't occurred for each exception. --- test/t/exception.rb | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/t/exception.rb b/test/t/exception.rb index d27813028..b54d01c46 100644 --- a/test/t/exception.rb +++ b/test/t/exception.rb @@ -373,12 +373,35 @@ assert('Raise in ensure') do end end -assert('Raise in rescue') do - assert_raise(ArgumentError) do - begin - raise "" # RuntimeError - rescue - raise ArgumentError +assert('GC in rescue') do + line = nil + begin + [1].each do + [2].each do + [3].each do + line = __LINE__; raise "XXX" + end + end + end + rescue => exception + GC.start + assert_equal("#{__FILE__}:#{line}:in Object.call", + exception.backtrace.first) + end +end + +assert('Method call in rescue') do + line = nil + begin + [1].each do + [2].each do + line = __LINE__; raise "XXX" + end + end + rescue => exception + [3].each do end + assert_equal("#{__FILE__}:#{line}:in Object.call", + exception.backtrace.first) end end -- cgit v1.2.3 From 0ebac02813d6506f92c9aaceaa00c6f902a56a03 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Tue, 29 Dec 2015 23:26:31 +0900 Subject: Skip backtrace related tests when backtrace isn't available --- test/t/exception.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test') diff --git a/test/t/exception.rb b/test/t/exception.rb index b54d01c46..742f4a044 100644 --- a/test/t/exception.rb +++ b/test/t/exception.rb @@ -373,7 +373,17 @@ assert('Raise in ensure') do end end +def backtrace_avaialble? + begin + raise "XXX" + rescue => exception + not exception.backtrace.empty? + end +end + assert('GC in rescue') do + skip "backtrace isn't avaialble" unless backtrace_avaialble? + line = nil begin [1].each do @@ -391,6 +401,8 @@ assert('GC in rescue') do end assert('Method call in rescue') do + skip "backtrace isn't avaialble" unless backtrace_avaialble? + line = nil begin [1].each do -- cgit v1.2.3