1
0
Fork 0
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:
zedshaw 2006-06-15 18:14:07 +00:00
parent 375a0b5c5e
commit 39c1bad626
5 changed files with 35 additions and 25 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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