Permalink
Browse files

Removed the mutex from the WEBrick adapter under the production envir…

…onment so concurrent requests can be served

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1482 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent ce44079 commit 4e0ffab8b05f5cc35996ac4866ee61cefb432af6 @dhh dhh committed Jun 22, 2005
@@ -124,20 +124,20 @@ def initialize(cgi)
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
View
@@ -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]
@@ -25,13 +25,13 @@
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
@@ -8,6 +8,24 @@
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 @@ def self.dispatch(options = {})
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 @@ def initialize(server, options)
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 @@ def handle_file(req, res)
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 @@ def handle_dispatch(req, res, origin = nil)
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

0 comments on commit 4e0ffab

Please sign in to comment.