diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2005-06-22 12:59:36 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2005-06-22 12:59:36 +0000 |
commit | 4e0ffab8b05f5cc35996ac4866ee61cefb432af6 (patch) | |
tree | 897aea07971f463340d944efadefe9d4dc678bfe | |
parent | ce44079818c9307ed20a2f11b2bf7933803f78f7 (diff) | |
download | rails-4e0ffab8b05f5cc35996ac4866ee61cefb432af6.tar.gz rails-4e0ffab8b05f5cc35996ac4866ee61cefb432af6.tar.bz2 rails-4e0ffab8b05f5cc35996ac4866ee61cefb432af6.zip |
Removed the mutex from the WEBrick adapter under the production environment so concurrent requests can be served
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1482 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r-- | actionpack/lib/action_controller/cgi_process.rb | 10 | ||||
-rw-r--r-- | railties/CHANGELOG | 2 | ||||
-rw-r--r-- | railties/lib/dispatcher.rb | 6 | ||||
-rw-r--r-- | railties/lib/webrick_server.rb | 96 |
4 files changed, 75 insertions, 39 deletions
diff --git a/actionpack/lib/action_controller/cgi_process.rb b/actionpack/lib/action_controller/cgi_process.rb index 9166a8d433..e4e86615c0 100644 --- a/actionpack/lib/action_controller/cgi_process.rb +++ b/actionpack/lib/action_controller/cgi_process.rb @@ -124,20 +124,20 @@ module ActionController #:nodoc: super() end - def out + def out(output = $stdout) convert_content_type!(@headers) - $stdout.binmode if $stdout.respond_to?(:binmode) - $stdout.sync = false + output.binmode if output.respond_to?(:binmode) + output.sync = false if output.respond_to?(:sync=) begin - print @cgi.header(@headers) + output.write(@cgi.header(@headers)) if @cgi.send(:env_table)['REQUEST_METHOD'] == 'HEAD' return elsif @body.respond_to?(:call) @body.call(self) else - print @body + output.write(@body) end rescue Errno::EPIPE => e # lost connection to the FCGI process -- ignore the output, then diff --git a/railties/CHANGELOG b/railties/CHANGELOG index d4423b4a83..444a918a7c 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Removed the mutex from the WEBrick adapter under the production environment so concurrent requests can be served + * Fixed that mailer generator generated fixtures/plural while units expected fixtures/singular #1457 [Scott Barron] * Added a 'whiny nil' that's aim to ensure that when users pass nil to methods where that isn't appropriate, instead of NoMethodError? and the name of some method used by the framework users will see a message explaining what type of object was expected. Only active in test and development environments by default #1209 [Michael Koziarski] diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb index 140d8e84a3..b2f9650e65 100644 --- a/railties/lib/dispatcher.rb +++ b/railties/lib/dispatcher.rb @@ -25,13 +25,13 @@ require 'breakpoint' class Dispatcher class << self - def dispatch(cgi = CGI.new, session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS) + def dispatch(cgi = CGI.new, session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout) begin request, response = ActionController::CgiRequest.new(cgi, session_options), ActionController::CgiResponse.new(cgi) prepare_application - ActionController::Routing::Routes.recognize!(request).process(request, response).out + ActionController::Routing::Routes.recognize!(request).process(request, response).out(output) rescue Object => exception - ActionController::Base.process_with_exception(request, response, exception).out + ActionController::Base.process_with_exception(request, response, exception).out(output) ensure reset_application end diff --git a/railties/lib/webrick_server.rb b/railties/lib/webrick_server.rb index bd8c287c9b..46451e2e52 100644 --- a/railties/lib/webrick_server.rb +++ b/railties/lib/webrick_server.rb @@ -8,6 +8,24 @@ include WEBrick ABSOLUTE_RAILS_ROOT = File.expand_path(RAILS_ROOT) +class CGI + def stdinput + @stdin || $stdin + end + + def stdinput=(input) + @stdin = input + end + + def env_table + @env_table || ENV + end + + def env_table=(table) + @env_table = table + end +end + class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet REQUEST_MUTEX = Mutex.new @@ -18,6 +36,10 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet server.mount('/', DispatchServlet, options) trap("INT") { server.shutdown } + + require File.join(@server_options[:server_root], "..", "config", "environment") unless defined?(RAILS_ROOT) + require "dispatcher" + server.start end @@ -31,20 +53,21 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet def service(req, res) begin unless handle_file(req, res) - REQUEST_MUTEX.lock + REQUEST_MUTEX.lock unless RAILS_ENV == 'production' unless handle_dispatch(req, res) raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." end end ensure - REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked? + unless RAILS_ENV == 'production' + REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked? + end end end def handle_file(req, res) begin req = req.dup - path = req.path.dup # Add .html if the last path piece has no . in it @@ -63,35 +86,13 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet end end - def handle_dispatch(req, res, origin = nil) - env = req.meta_vars.clone - env.delete "SCRIPT_NAME" - env["QUERY_STRING"] = req.request_uri.query - env["REQUEST_URI"] = origin if origin - - data = nil - $old_stdin, $old_stdout = $stdin, $stdout - $stdin, $stdout = StringIO.new(req.body || ""), StringIO.new - - begin - require 'cgi' - CGI.send(:define_method, :env_table) { env } - - load File.join(@server_options[:server_root], "dispatch.rb") - - $stdout.rewind - data = $stdout.read - ensure - $stdin, $stdout = $old_stdin, $old_stdout - end + def handle_dispatch(req, res, origin = nil) + data = StringIO.new + Dispatcher.dispatch(create_cgi(req, origin), ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, data) - raw_header, body = *data.split(/^[\xd\xa]+/on, 2) - header = WEBrick::HTTPUtils::parse_header(raw_header) - if /^(\d+)/ =~ header['status'][0] - res.status = $1.to_i - header.delete('status') - end - res.cookies.concat header.delete('set-cookie') + header, body = extract_header_and_body(data) + assign_status(res, header) + res.cookies.concat(header.delete('set-cookie')) header.each { |key, val| res[key] = val.join(", ") } res.body = body @@ -100,4 +101,37 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet p err, err.backtrace return false end + + private + def create_cgi(req, origin) + cgi = CGI.new + cgi.env_table = create_env_table(req, origin) + cgi.stdinput = req.body || "" + return cgi + end + + def create_env_table(req, origin) + env = req.meta_vars.clone + env.delete "SCRIPT_NAME" + env["QUERY_STRING"] = req.request_uri.query + env["REQUEST_URI"] = origin if origin + return env + end + + def extract_header_and_body(data) + data.rewind + data = data.read + + raw_header, body = *data.split(/^[\xd\xa]+/on, 2) + header = WEBrick::HTTPUtils::parse_header(raw_header) + + return header, body + end + + def assign_status(res, header) + if /^(\d+)/ =~ header['status'][0] + res.status = $1.to_i + header.delete('status') + end + end end |