diff --git a/lib/webrick/httpserver.rb b/lib/webrick/httpserver.rb index 0d261bf..2017fa2 100644 --- a/lib/webrick/httpserver.rb +++ b/lib/webrick/httpserver.rb @@ -79,7 +79,12 @@ def run(sock) timeout -= 0.5 end raise HTTPStatus::EOFError if timeout <= 0 || @status != :Running - raise HTTPStatus::EOFError if sock.eof? + begin + raise HTTPStatus::EOFError if sock.eof? + rescue Errno::ECONNRESET + raise HTTPStatus::EOFError + end + req.parse(sock) res.request_method = req.request_method res.request_uri = req.request_uri diff --git a/test/webrick/test_httpserver.rb b/test/webrick/test_httpserver.rb index 0c5a614..c74b49f 100644 --- a/test/webrick/test_httpserver.rb +++ b/test/webrick/test_httpserver.rb @@ -562,4 +562,35 @@ def test_accept_put_requests end end end + + def test_client_connection_reset + log_tester = lambda {|log, access_log| + assert_empty log + } + + TestWEBrick.start_httpserver({}, log_tester) do |server, addr, port, log| + server.mount_proc("/", lambda {|req, res| res.body = "hello!" }) + + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/") + req['Connection'] = 'Keep-Alive' + + # Simulate a client, which makes a request, reads the response + # and then resets the connection. + http.request(req) do |res| + res.body # read body to completion + + # Fish the socket out of the Net::HTTP object, configure it to + # linger on close, and then close it abruptly. This will reset + # the socket, discard any pending data cause a RST to be sent. + socket = http.instance_variable_get(:@socket).io + socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1,0].pack('ii')) + socket.close + end + + # delay the server shutdown so that WEBrick::HTTPServer#run begins + # a new iteration. + sleep 0.1 + end + end end