Description
If a new exception is created and raised from within a rescue block then the traceback begins with lines from the old exception that was being rescued. What I expected and wanted was just the traceback for the new exception showing where it had been raised.
In the example below I wanted the traceback to just show where Net::HTTP.start
had been called from, and not all the calls within net/http
that were part of the old exception caught by the rescue
. The reason for raising a new exception was to hide all the traceback from inside net/http
, which obscures where it was called from.
The lines from the old traceback appear even though $@
and the the old exception’s backtrace have both been set to []
. Why is this and how can it be prevented? Is the old backtrace held in another global variable that can be cleared before creating and raising the new exception?
This is using ruby 2.6.6 in Windows 10 x64
Example
Code
require 'net/http'
include Net
uri = URI('http://wrong.host/xxx')
begin
http = Net::HTTP.start(uri.host, uri.port)
p http
rescue StandardError => old_e
old_e.set_backtrace([])
$@ = []
new_e = StandardError.new('My message')
new_e.set_backtrace(caller)
puts "new exception = #{new_e.inspect}"
puts "new backtrace = <#{new_e.backtrace.to_a.join("\n")}>"
puts "new bt_locns = <#{new_e.backtrace_locations.to_a.join("\n")}>"
puts "new \$@ = <#{[email protected]_a.join("\n")}>"
raise new_e
end
Output
D:\Docs\Dev\Ruby\Tests>test_exceptions_1.rb
new exception = #<StandardError: My message>
new backtrace = <D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb:8:in `<main>'>
new bt_locns = <>
new $@ = <>
Traceback (most recent call last):
9: from D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb:9:in `<main>'
8: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:605:in `start'
7: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:925:in `start'
6: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:930:in `do_start'
5: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:945:in `connect'
4: from C:/Ruby26-x64/lib/ruby/2.6.0/timeout.rb:103:in `timeout'
3: from C:/Ruby26-x64/lib/ruby/2.6.0/timeout.rb:93:in `block in timeout'
2: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:947:in `block in connect'
1: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:947:in `open'
C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:947:in `initialize': getaddrinfo: No such host is known. (SocketError)
D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb: Failed to open TCP connection to wrong.host:80 (getaddrinfo: No such host is known. ) (SocketError)
D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb:8:in `<main>': My message (StandardError)