From 30e3c6abe542c6a9f5955e1d65896a0c3bab534f Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 16 Dec 2017 01:22:40 +0000 Subject: avoid reusing env on hijack Hijackers may capture and reuse `env' indefinitely, so we must not use it in those cases for future requests. For non-hijack requests, we continue to reuse the `env' object to reduce memory recycling. Reported-and-tested-by: Sam Saffron --- lib/unicorn/http_request.rb | 1 + lib/unicorn/http_response.rb | 5 +++-- lib/unicorn/http_server.rb | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/unicorn') diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb index f83a566..d713b19 100644 --- a/lib/unicorn/http_request.rb +++ b/lib/unicorn/http_request.rb @@ -98,6 +98,7 @@ class Unicorn::HttpParser # for rack.hijack, we respond to this method so no extra allocation # of a proc object def call + hijacked! env['rack.hijack_io'] = env['unicorn.socket'] end diff --git a/lib/unicorn/http_response.rb b/lib/unicorn/http_response.rb index ec128e4..b23e521 100644 --- a/lib/unicorn/http_response.rb +++ b/lib/unicorn/http_response.rb @@ -21,13 +21,13 @@ module Unicorn::HttpResponse # writes the rack_response to socket as an HTTP response def http_response_write(socket, status, headers, body, - response_start_sent=false) + req = Unicorn::HttpRequest.new) hijack = nil if headers code = status.to_i msg = STATUS_CODES[code] - start = response_start_sent ? ''.freeze : 'HTTP/1.1 '.freeze + start = req.response_start_sent ? ''.freeze : 'HTTP/1.1 '.freeze buf = "#{start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \ "Date: #{httpdate}\r\n" \ "Connection: close\r\n" @@ -52,6 +52,7 @@ module Unicorn::HttpResponse end if hijack + req.hijacked! hijack.call(socket) else body.each { |chunk| socket.write(chunk) } diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb index f33aa25..8674729 100644 --- a/lib/unicorn/http_server.rb +++ b/lib/unicorn/http_server.rb @@ -614,8 +614,7 @@ class Unicorn::HttpServer return if @request.hijacked? end @request.headers? or headers = nil - http_response_write(client, status, headers, body, - @request.response_start_sent) + http_response_write(client, status, headers, body, @request) ensure body.respond_to?(:close) and body.close end -- cgit v1.2.3-24-ge0c7