diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/unicorn.rb | 27 | ||||
-rw-r--r-- | lib/unicorn/configurator.rb | 3 | ||||
-rw-r--r-- | lib/unicorn/const.rb | 3 | ||||
-rw-r--r-- | lib/unicorn/http_request.rb | 37 | ||||
-rw-r--r-- | lib/unicorn/http_response.rb | 15 | ||||
-rw-r--r-- | lib/unicorn/socket_helper.rb (renamed from lib/unicorn/socket.rb) | 13 |
6 files changed, 34 insertions, 64 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb index 208e6da..1f1dd45 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -1,7 +1,6 @@ -require 'logger' require 'fcntl' -require 'unicorn/socket' +require 'unicorn/socket_helper' require 'unicorn/const' require 'unicorn/http_request' require 'unicorn/http_response' @@ -27,13 +26,13 @@ module Unicorn include ::Unicorn::SocketHelper SIG_QUEUE = [] - DEFAULT_START_CTX = { + START_CTX = { :argv => ARGV.map { |arg| arg.dup }, # don't rely on Dir.pwd here since it's not symlink-aware, and # symlink dirs are the default with Capistrano... :cwd => `/bin/sh -c pwd`.chomp("\n"), :zero => $0.dup, - }.freeze + } Worker = Struct.new(:nr, :tempfile) unless defined?(Worker) class Worker @@ -48,9 +47,6 @@ module Unicorn # HttpServer.workers.join to join the thread that's processing # incoming requests on the socket. def initialize(app, options = {}) - start_ctx = options.delete(:start_ctx) - @start_ctx = DEFAULT_START_CTX.dup - @start_ctx.merge!(start_ctx) if start_ctx @app = app @workers = Hash.new @io_purgatory = [] # prevents IO objects in here from being GC-ed @@ -307,7 +303,7 @@ module Unicorn end end - # reexecutes the @start_ctx with a new binary + # reexecutes the START_CTX with a new binary def reexec if @reexec_pid > 0 begin @@ -337,8 +333,8 @@ module Unicorn @reexec_pid = fork do listener_fds = @listeners.map { |sock| sock.fileno } ENV['UNICORN_FD'] = listener_fds.join(',') - Dir.chdir(@start_ctx[:cwd]) - cmd = [ @start_ctx[:zero] ] + @start_ctx[:argv] + Dir.chdir(START_CTX[:cwd]) + cmd = [ START_CTX[:zero] ] + START_CTX[:argv] # avoid leaking FDs we don't know about, but let before_exec # unset FD_CLOEXEC, if anything else in the app eventually @@ -379,9 +375,9 @@ module Unicorn (0...@worker_processes).each do |worker_nr| @workers.values.include?(worker_nr) and next begin - Dir.chdir(@start_ctx[:cwd]) + Dir.chdir(START_CTX[:cwd]) rescue Errno::ENOENT => err - logger.fatal "#{err.inspect} (#{@start_ctx[:cwd]})" + logger.fatal "#{err.inspect} (#{START_CTX[:cwd]})" SIG_QUEUE << :QUIT # forcibly emulate SIGQUIT return end @@ -431,10 +427,11 @@ module Unicorn trap(:CHLD, 'DEFAULT') SIG_QUEUE.clear proc_name "worker[#{worker.nr}]" + START_CTX.clear @rd_sig.close if @rd_sig @wr_sig.close if @wr_sig @workers.values.each { |other| other.tempfile.close rescue nil } - @start_ctx = @workers = @rd_sig = @wr_sig = nil + @workers = @rd_sig = @wr_sig = nil @listeners.each { |sock| sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) } worker.tempfile.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) @after_fork.call(self, worker) # can drop perms @@ -588,8 +585,8 @@ module Unicorn end def proc_name(tag) - $0 = ([ File.basename(@start_ctx[:zero]), tag ] + - @start_ctx[:argv]).join(' ') + $0 = ([ File.basename(START_CTX[:zero]), tag ] + + START_CTX[:argv]).join(' ') end end diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index b27121e..bd06996 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -1,5 +1,4 @@ -require 'unicorn/socket' -require 'unicorn/const' +require 'socket' require 'logger' module Unicorn diff --git a/lib/unicorn/const.rb b/lib/unicorn/const.rb index 80731ab..c05d333 100644 --- a/lib/unicorn/const.rb +++ b/lib/unicorn/const.rb @@ -58,8 +58,6 @@ module Unicorn UNICORN_VERSION="0.5.3".freeze - UNICORN_TMP_BASE="unicorn".freeze - DEFAULT_HOST = "0.0.0.0".freeze # default TCP listen host address DEFAULT_PORT = "8080".freeze # default TCP listen port DEFAULT_LISTEN = "#{DEFAULT_HOST}:#{DEFAULT_PORT}".freeze @@ -82,7 +80,6 @@ module Unicorn CONTENT_LENGTH="CONTENT_LENGTH".freeze REMOTE_ADDR="REMOTE_ADDR".freeze HTTP_X_FORWARDED_FOR="HTTP_X_FORWARDED_FOR".freeze - QUERY_STRING="QUERY_STRING".freeze RACK_INPUT="rack.input".freeze end diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb index 399aee5..24da085 100644 --- a/lib/unicorn/http_request.rb +++ b/lib/unicorn/http_request.rb @@ -1,5 +1,4 @@ require 'tempfile' -require 'uri' require 'stringio' # compiled extension @@ -19,11 +18,11 @@ module Unicorn "rack.multiprocess" => true, "rack.multithread" => false, "rack.run_once" => false, - "rack.version" => [0, 1], - "SCRIPT_NAME" => "", + "rack.version" => [0, 1].freeze, + "SCRIPT_NAME" => "".freeze, # this is not in the Rack spec, but some apps may rely on it - "SERVER_SOFTWARE" => "Unicorn #{Const::UNICORN_VERSION}" + "SERVER_SOFTWARE" => "Unicorn #{Const::UNICORN_VERSION}".freeze }.freeze def initialize(logger) @@ -56,6 +55,16 @@ module Unicorn # This does minimal exception trapping and it is up to the caller # to handle any socket errors (e.g. user aborted upload). def read(socket) + # From http://www.ietf.org/rfc/rfc3875: + # "Script authors should be aware that the REMOTE_ADDR and + # REMOTE_HOST meta-variables (see sections 4.1.8 and 4.1.9) + # may not identify the ultimate source of the request. They + # identify the client for the immediate request to the server; + # that client may be a proxy, gateway, or other intermediary + # acting on behalf of the actual source client." + @params[Const::REMOTE_ADDR] = + TCPSocket === socket ? socket.peeraddr.last : '127.0.0.1' + # short circuit the common case with small GET requests first @parser.execute(@params, read_socket(socket)) and return handle_body(socket) @@ -71,7 +80,7 @@ module Unicorn rescue HttpParserError => e @logger.error "HTTP parse error, malformed request " \ "(#{@params[Const::HTTP_X_FORWARDED_FOR] || - socket.unicorn_peeraddr}): #{e.inspect}" + @params[Const::REMOTE_ADDR]}): #{e.inspect}" @logger.error "REQUEST DATA: #{data.inspect}\n---\n" \ "PARAMS: #{@params.inspect}\n---\n" raise e @@ -87,7 +96,7 @@ module Unicorn remain = content_length - http_body.length # must read more data to complete body - @body = remain < Const::MAX_BODY ? StringIO.new : Tempfile.new('') + @body = remain < Const::MAX_BODY ? StringIO.new : Tempfile.new('unicorn') @body.binmode @body.sync = true @body.syswrite(http_body) @@ -116,22 +125,6 @@ module Unicorn # over the HTTP response. # @params["unicorn.client"] = socket - # From http://www.ietf.org/rfc/rfc3875: - # "Script authors should be aware that the REMOTE_ADDR and - # REMOTE_HOST meta-variables (see sections 4.1.8 and 4.1.9) - # may not identify the ultimate source of the request. They - # identify the client for the immediate request to the server; - # that client may be a proxy, gateway, or other intermediary - # acting on behalf of the actual source client." - @params[Const::REMOTE_ADDR] = socket.unicorn_peeraddr - - # It might be a dumbass full host request header - @params[Const::PATH_INFO] = ( - @params[Const::REQUEST_PATH] ||= - URI.parse(@params[Const::REQUEST_URI]).path) or - raise "No REQUEST_PATH" - - @params[Const::QUERY_STRING] ||= '' @params[Const::RACK_INPUT] = @body @params.update(DEF_PARAMS) end diff --git a/lib/unicorn/http_response.rb b/lib/unicorn/http_response.rb index b355ad4..6b6fa07 100644 --- a/lib/unicorn/http_response.rb +++ b/lib/unicorn/http_response.rb @@ -64,15 +64,12 @@ module Unicorn # write(2) can return short on slow devices like sockets as well # as fail with EINTR if a signal was caught. def self.socket_write(socket, buffer) - loop do - begin - written = socket.syswrite(buffer) - return written if written == buffer.length - buffer = buffer[written..-1] - rescue Errno::EINTR - retry - end - end + begin + written = socket.syswrite(buffer) + return written if written == buffer.length + buffer = buffer[written..-1] + rescue Errno::EINTR + end while true end end diff --git a/lib/unicorn/socket.rb b/lib/unicorn/socket_helper.rb index 5a3bfd7..850ad85 100644 --- a/lib/unicorn/socket.rb +++ b/lib/unicorn/socket_helper.rb @@ -1,18 +1,5 @@ require 'socket' -class UNIXSocket - UNICORN_PEERADDR = '127.0.0.1'.freeze - def unicorn_peeraddr - UNICORN_PEERADDR - end -end - -class TCPSocket - def unicorn_peeraddr - peeraddr.last - end -end - module Unicorn module SocketHelper include Socket::Constants |