mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Major bug fixed where sockets would get leaked if the client closed early (or any socket errors from the client).
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@238 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
parent
375a0b5c5e
commit
39c1bad626
5 changed files with 35 additions and 25 deletions
2
Rakefile
2
Rakefile
|
@ -33,7 +33,7 @@ task :ragel do
|
|||
end
|
||||
|
||||
task :site_webgen do
|
||||
sh %{pushd doc/site; webgen; scp -r `find output -name "*.html" -print` #{ENV['SSH_USER']}@rubyforge.org:/var/www/gforge-projects/mongrel/; popd }
|
||||
sh %{pushd doc/site; webgen; scp -r output/* #{ENV['SSH_USER']}@rubyforge.org:/var/www/gforge-projects/mongrel/; popd }
|
||||
end
|
||||
|
||||
task :site_rdoc do
|
||||
|
|
|
@ -6,16 +6,6 @@ require 'mongrel/rails'
|
|||
require 'etc'
|
||||
|
||||
|
||||
class Version < GemPlugin::Plugin "/commands"
|
||||
include Mongrel::Command::Base
|
||||
|
||||
def run
|
||||
puts "Version #{Mongrel::Const::MONGREL_VERSION}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Start < GemPlugin::Plugin "/commands"
|
||||
include Mongrel::Command::Base
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ module Mongrel
|
|||
def send_status(content_length=nil)
|
||||
if not @status_sent
|
||||
content_length ||= @body.length
|
||||
@socket.write(Const::STATUS_FORMAT % [status, HTTP_STATUS_CODES[@status], content_length])
|
||||
write(Const::STATUS_FORMAT % [status, HTTP_STATUS_CODES[@status], content_length])
|
||||
@status_sent = true
|
||||
end
|
||||
end
|
||||
|
@ -380,7 +380,7 @@ module Mongrel
|
|||
def send_header
|
||||
if not @header_sent
|
||||
@header.out.rewind
|
||||
@socket.write(@header.out.read + Const::LINE_END)
|
||||
write(@header.out.read + Const::LINE_END)
|
||||
@header_sent = true
|
||||
end
|
||||
end
|
||||
|
@ -388,7 +388,7 @@ module Mongrel
|
|||
def send_body
|
||||
if not @body_sent
|
||||
@body.rewind
|
||||
@socket.write(@body.read)
|
||||
write(@body.read)
|
||||
@body_sent = true
|
||||
end
|
||||
end
|
||||
|
@ -404,22 +404,31 @@ module Mongrel
|
|||
def send_file(path)
|
||||
File.open(path, "rb") do |f|
|
||||
if @socket.respond_to? :sendfile
|
||||
@socket.sendfile(f)
|
||||
begin
|
||||
@socket.sendfile(f)
|
||||
rescue => details
|
||||
socket_error(details)
|
||||
end
|
||||
else
|
||||
while chunk = f.read(Const::CHUNK_SIZE) and chunk.length > 0
|
||||
@socket.write(chunk)
|
||||
write(chunk)
|
||||
end
|
||||
end
|
||||
|
||||
@body_send = true
|
||||
end
|
||||
rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
|
||||
end
|
||||
|
||||
def socket_error(details)
|
||||
# ignore these since it means the client closed off early
|
||||
STDERR.puts "Client closed socket early requesting file #{path}: #$!"
|
||||
@socket.close unless @socket.closed?
|
||||
done = true
|
||||
raise details
|
||||
end
|
||||
|
||||
def write(data)
|
||||
@socket.write(data)
|
||||
rescue => details
|
||||
socket_error(details)
|
||||
end
|
||||
|
||||
# This takes whatever has been done to header and body and then writes it in the
|
||||
|
@ -430,6 +439,14 @@ module Mongrel
|
|||
send_body
|
||||
end
|
||||
|
||||
# Used during error conditions to mark the response as "done" so there isn't any more processing
|
||||
# sent to the client.
|
||||
def done=(val)
|
||||
@status_sent = true
|
||||
@header_sent = true
|
||||
@body_sent = true
|
||||
end
|
||||
|
||||
def done
|
||||
(@status_sent and @header_sent and @body_sent)
|
||||
end
|
||||
|
@ -530,11 +547,11 @@ module Mongrel
|
|||
# Process each handler in registered order until we run out or one finalizes the response.
|
||||
handlers.each do |handler|
|
||||
handler.process(request, response)
|
||||
break if response.done
|
||||
break if response.done or client.closed?
|
||||
end
|
||||
|
||||
# And finally, if nobody closed the response off, we finalize it.
|
||||
if not response.done
|
||||
unless response.done or client.closed?
|
||||
response.finished
|
||||
end
|
||||
else
|
||||
|
@ -560,7 +577,7 @@ module Mongrel
|
|||
STDERR.puts "#{Time.now}: ERROR: #$!"
|
||||
STDERR.puts details.backtrace.join("\n")
|
||||
ensure
|
||||
client.close
|
||||
client.close unless client.closed?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -186,6 +186,9 @@ module Mongrel
|
|||
if !cmd_name or cmd_name == "?" or cmd_name == "help"
|
||||
print_command_list
|
||||
return true
|
||||
elsif cmd_name == "--version"
|
||||
STDERR.puts "Mongrel Web Server #{Mongrel::Const::MONGREL_VERSION}"
|
||||
return true
|
||||
end
|
||||
|
||||
# command exists, set it up and validate it
|
||||
|
@ -194,7 +197,7 @@ module Mongrel
|
|||
rescue
|
||||
STDERR.puts "INVALID COMMAND: #$!"
|
||||
print_command_list
|
||||
return
|
||||
return false
|
||||
end
|
||||
|
||||
# Normally the command is NOT valid right after being created
|
||||
|
@ -208,6 +211,7 @@ module Mongrel
|
|||
command.run
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
|
@ -256,8 +256,7 @@ module Mongrel
|
|||
response.start(403) {|head,out| out.write(ONLY_HEAD_GET) }
|
||||
end
|
||||
rescue => details
|
||||
STDERR.puts "Error accessing file #{req_path}: #{details}"
|
||||
STDERR.puts details.backtrace.join("\n")
|
||||
STDERR.puts "Error sending file #{req_path}: #{details}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue