Fix error raised by Net::HTTPResponse#inflater if the block raises

* See https://bugs.ruby-lang.org/issues/13882#note-6
This commit is contained in:
Benoit Daloze 2020-05-30 10:29:24 +02:00
Родитель 5b4b82b712
Коммит 5a79d8e050
2 изменённых файлов: 70 добавлений и 2 удалений

Просмотреть файл

@ -268,12 +268,13 @@ class Net::HTTPResponse
begin
yield inflate_body_io
success = true
ensure
orig_err = $!
begin
inflate_body_io.finish
rescue => err
raise orig_err || err
# Ignore #finish's error if there is an exception from yield
raise err if success
end
end
when 'none', 'identity' then

Просмотреть файл

@ -24,3 +24,70 @@ describe "Net::HTTP.get" do
end
end
end
describe "Net::HTTP.get" do
describe "when reading gzipped contents" do
def start_threads
require 'zlib'
server = nil
server_thread = Thread.new do
server = TCPServer.new("127.0.0.1", 0)
begin
c = server.accept
ensure
server.close
end
c.print "HTTP/1.1 200\r\n"
c.print "Content-Type: text/plain\r\n"
c.print "Content-Encoding: gzip\r\n"
s = StringIO.new
z = Zlib::GzipWriter.new(s)
begin
z.write 'Hello World!'
ensure
z.close
end
c.print "Content-Length: #{s.length}\r\n\r\n"
# Write partial gzip content
c.write s.string.byteslice(0..-2)
c.flush
c
end
Thread.pass until server && server_thread.stop?
client_thread = Thread.new do
Thread.current.report_on_exception = false
Net::HTTP.get("127.0.0.1", '/', server.connect_address.ip_port)
end
Thread.pass until client_thread.stop?
[server_thread, client_thread]
end
it "propagates exceptions interrupting the thread and does not replace it with Zlib::BufError" do
my_exception = Class.new(RuntimeError)
server_thread, client_thread = start_threads
socket = server_thread.value
begin
client_thread.raise my_exception, "my exception"
-> { client_thread.value }.should raise_error(my_exception)
ensure
socket.close
end
end
ruby_version_is "2.8" do # https://bugs.ruby-lang.org/issues/13882#note-6
it "lets the kill Thread exception goes through and does not replace it with Zlib::BufError" do
server_thread, client_thread = start_threads
socket = server_thread.value
begin
client_thread.kill
client_thread.value.should == nil
ensure
socket.close
end
end
end
end
end