From c01d080fd6b02de696c46547bdb0e95f0f62386b Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 7 Mar 2013 15:49:03 -0700 Subject: Exception handling for controllers using ActionController::Live Any exceptions that occured at the view or controller level for a controller using ActionController::Live would cause the server to either hang with an open socket indefinitely, or immediately crash (depending on whether the server was launched with rails s or directly). Changed the behavior of exceptions to act the same as streaming templates for html requests, and allow for an on_error callback if needed. --- actionpack/lib/action_controller/metal/live.rb | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'actionpack/lib/action_controller/metal') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index fb664a69dd..0a77352e57 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -56,6 +56,14 @@ module ActionController super @buf.push nil end + + def on_error(&block) + @error_callback = block + end + + def call_on_error + @error_callback.call + end end class Response < ActionDispatch::Response #:nodoc: all @@ -121,6 +129,16 @@ module ActionController begin super(name) + rescue => e + begin + @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html + @_response.stream.call_on_error + rescue => exceptionception + log_error(exceptionception) + ensure + log_error(e) + @_response.stream.close + end ensure @_response.commit! end @@ -129,6 +147,16 @@ module ActionController @_response.await_commit end + def log_error(exception) + logger = ActionController::Base.logger + return unless logger + + message = "\n#{exception.class} (#{exception.message}):\n" + message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code) + message << " " << exception.backtrace.join("\n ") + logger.fatal("#{message}\n\n") + end + def response_body=(body) super response.stream.close if response -- cgit v1.2.3