aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/metal/live.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/metal/live.rb')
-rw-r--r--actionpack/lib/action_controller/metal/live.rb79
1 files changed, 42 insertions, 37 deletions
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index 27b3eb4e58..fc20e7a421 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -36,8 +36,7 @@ module ActionController
extend ActiveSupport::Concern
module ClassMethods
- def make_response!(response)
- request = response.request
+ def make_response!(request)
if request.get_header("HTTP_VERSION") == "HTTP/1.0"
super
else
@@ -223,12 +222,6 @@ module ActionController
jar.write self unless committed?
end
- def before_sending
- super
- request.cookie_jar.commit!
- headers.freeze
- end
-
def build_buffer(response, body)
buf = Live::Buffer.new response
body.each { |part| buf.write part }
@@ -244,39 +237,55 @@ module ActionController
# This processes the action in a child thread. It lets us return the
# response code and headers back up the rack stack, and still process
# the body in parallel with sending data to the client
- Thread.new {
- t2 = Thread.current
- t2.abort_on_exception = true
-
- # Since we're processing the view in a different thread, copy the
- # thread locals from the main thread to the child thread. :'(
- locals.each { |k,v| t2[k] = v }
-
- begin
- super(name)
- rescue => e
- if @_response.committed?
- begin
- @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
- @_response.stream.call_on_error
- rescue => exception
- log_error(exception)
- ensure
- log_error(e)
- @_response.stream.close
+ new_controller_thread {
+ ActiveSupport::Dependencies.interlock.running do
+ t2 = Thread.current
+
+ # Since we're processing the view in a different thread, copy the
+ # thread locals from the main thread to the child thread. :'(
+ locals.each { |k,v| t2[k] = v }
+
+ begin
+ super(name)
+ rescue => e
+ if @_response.committed?
+ begin
+ @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
+ @_response.stream.call_on_error
+ rescue => exception
+ log_error(exception)
+ ensure
+ log_error(e)
+ @_response.stream.close
+ end
+ else
+ error = e
end
- else
- error = e
+ ensure
+ @_response.commit!
end
- ensure
- @_response.commit!
end
}
- @_response.await_commit
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+ @_response.await_commit
+ end
+
raise error if error
end
+ # Spawn a new thread to serve up the controller in. This is to get
+ # around the fact that Rack isn't based around IOs and we need to use
+ # a thread to stream data from the response bodies. Nobody should call
+ # this method except in Rails internals. Seriously!
+ def new_controller_thread # :nodoc:
+ Thread.new {
+ t2 = Thread.current
+ t2.abort_on_exception = true
+ yield
+ }
+ end
+
def log_error(exception)
logger = ActionController::Base.logger
return unless logger
@@ -293,9 +302,5 @@ module ActionController
super
response.close if response
end
-
- def set_response!(response)
- @_response = self.class.make_response! response
- end
end
end