diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2007-09-23 11:20:25 +0000 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2007-09-23 11:20:25 +0000 |
commit | 547447ad2abf72f6f5eb57a76b1a830feca34d90 (patch) | |
tree | 9fd1c0e044e8873b46e22561fedb57405e8e9d73 /railties/lib | |
parent | 4e3ed5bc44f6cd20c9e353ab63fd24b92a7942be (diff) | |
download | rails-547447ad2abf72f6f5eb57a76b1a830feca34d90.tar.gz rails-547447ad2abf72f6f5eb57a76b1a830feca34d90.tar.bz2 rails-547447ad2abf72f6f5eb57a76b1a830feca34d90.zip |
RailsFCGIHandler tests. Closes #9630.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7593 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'railties/lib')
-rw-r--r-- | railties/lib/fcgi_handler.rb | 130 |
1 files changed, 68 insertions, 62 deletions
diff --git a/railties/lib/fcgi_handler.rb b/railties/lib/fcgi_handler.rb index 5bb26e4598..2b0d7b1916 100644 --- a/railties/lib/fcgi_handler.rb +++ b/railties/lib/fcgi_handler.rb @@ -41,38 +41,72 @@ class RailsFCGIHandler # Start error timestamp at 11 seconds ago. @last_error_on = Time.now - 11 - - dispatcher_log :info, "starting" end def process!(provider = FCGI) - # Make a note of $" so we can safely reload this instance. - mark! - - run_gc! if gc_request_period + mark_features! + + dispatcher_log :info, 'starting' + process_each_request provider + dispatcher_log :info, 'stopping gracefully' + + rescue Exception => error + case error + when SystemExit + dispatcher_log :info, 'stopping after explicit exit' + when SignalException + dispatcher_error error, 'stopping after unhandled signal' + else + # Retry if exceptions occur more than 10 seconds apart. + if Time.now - @last_error_on > 10 + @last_error_on = Time.now + dispatcher_error error, 'retrying after unhandled exception' + retry + else + dispatcher_error error, 'stopping after unhandled exception within 10 seconds of the last' + end + end + end - process_each_request!(provider) - GC.enable - dispatcher_log :info, "terminated gracefully" + protected + def process_each_request(provider) + cgi = nil - rescue SystemExit => exit_error - dispatcher_log :info, "terminated by explicit exit" + provider.each_cgi do |cgi| + process_request(cgi) - rescue Exception => fcgi_error # FCGI errors - # retry on errors that would otherwise have terminated the FCGI process, - # but only if they occur more than 10 seconds apart. - if !(SignalException === fcgi_error) && Time.now - @last_error_on > 10 - @last_error_on = Time.now - dispatcher_error(fcgi_error, "almost killed by this error") - retry - else - dispatcher_error(fcgi_error, "killed by this error") + case when_ready + when :reload + reload! + when :restart + close_connection(cgi) + restart! + when :exit + close_connection(cgi) + break + end + end + rescue SignalException => signal + raise unless signal.message == 'SIGUSR1' + close_connection(cgi) end - end + def process_request(cgi) + @when_ready = nil + gc_countdown + + with_signal_handler 'USR1' do + begin + Dispatcher.dispatch(cgi) + rescue SignalException, SystemExit + raise + rescue Exception => error + dispatcher_error error, 'unhandled dispatch error' + end + end + end - protected def logger @logger ||= Logger.new(@log_file_path) end @@ -97,10 +131,12 @@ class RailsFCGIHandler end def install_signal_handler(signal, handler = nil) - handler ||= method("#{SIGNALS[signal]}_handler").to_proc - trap(signal, handler) - rescue ArgumentError - dispatcher_log :warn, "Ignoring unsupported signal #{signal}." + if SIGNALS.include?(signal) && self.class.method_defined?(name = "#{SIGNALS[signal]}_handler") + handler ||= method(name).to_proc + trap(signal, handler) + else + dispatcher_log :warn, "Ignoring unsupported signal #{signal}." + end end def with_signal_handler(signal) @@ -111,12 +147,12 @@ class RailsFCGIHandler end def exit_now_handler(signal) - dispatcher_log :info, "asked to terminate immediately" + dispatcher_log :info, "asked to stop immediately" exit end def exit_handler(signal) - dispatcher_log :info, "asked to terminate ASAP" + dispatcher_log :info, "asked to stop ASAP" @when_ready = :exit end @@ -130,38 +166,6 @@ class RailsFCGIHandler @when_ready = :restart end - def process_each_request!(provider) - cgi = nil - provider.each_cgi do |cgi| - with_signal_handler 'USR1' do - process_request(cgi) - end - - case when_ready - when :reload - reload! - when :restart - close_connection(cgi) - restart! - when :exit - close_connection(cgi) - break - end - - gc_countdown - end - rescue SignalException => signal - raise unless signal.message == 'SIGUSR1' - close_connection(cgi) if cgi - end - - def process_request(cgi) - Dispatcher.dispatch(cgi) - rescue Exception => e # errors from CGI dispatch - raise if SignalException === e - dispatcher_error(e) - end - def restart! config = ::Config::CONFIG ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT'] @@ -184,7 +188,8 @@ class RailsFCGIHandler dispatcher_log :info, "reloaded" end - def mark! + # Make a note of $" so we can safely reload this instance. + def mark_features! @features = $".clone end @@ -201,12 +206,13 @@ class RailsFCGIHandler def gc_countdown if gc_request_period + @gc_request_countdown ||= gc_request_period @gc_request_countdown -= 1 run_gc! if @gc_request_countdown <= 0 end end def close_connection(cgi) - cgi.instance_variable_get("@request").finish + cgi.instance_variable_get("@request").finish if cgi end end |