aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2005-07-02 04:52:14 +0000
committerJeremy Kemper <jeremy@bitsweat.net>2005-07-02 04:52:14 +0000
commit5650bc90940bd850a2f44bd3b58549d6b336dcd0 (patch)
tree83e430d5ac4e7b517c86a6a478bbfdf9d2b61420 /railties/lib
parentb8294932204474a8d00e80cf636cc048d23684ed (diff)
downloadrails-5650bc90940bd850a2f44bd3b58549d6b336dcd0.tar.gz
rails-5650bc90940bd850a2f44bd3b58549d6b336dcd0.tar.bz2
rails-5650bc90940bd850a2f44bd3b58549d6b336dcd0.zip
r1588@asus: jeremy | 2005-07-02 03:14:45 -0700
Optional periodic garbage collection for dispatch.fcgi. Graceful exit on TERM also (a la Apache1). Ignore signals the platform does not support, such as USR1 on Windows. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1592 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/fcgi_handler.rb79
1 files changed, 66 insertions, 13 deletions
diff --git a/railties/lib/fcgi_handler.rb b/railties/lib/fcgi_handler.rb
index f615ff6d34..f489627985 100644
--- a/railties/lib/fcgi_handler.rb
+++ b/railties/lib/fcgi_handler.rb
@@ -3,41 +3,77 @@ require 'logger'
require 'dispatcher'
class RailsFCGIHandler
+ SIGNALS = {
+ 'HUP' => :reload,
+ 'TERM' => :graceful_exit,
+ 'USR1' => :graceful_exit
+ }
+
attr_reader :when_ready
attr_reader :processing
- def self.process!
- new.process!
+ attr_accessor :log_file_path
+ attr_accessor :gc_request_period
+
+
+ # Initialize and run the FastCGI instance, passing arguments through to new.
+ def self.process!(*args, &block)
+ new(*args, &block).process!
end
- def initialize(log_file_path = "#{RAILS_ROOT}/log/fastcgi.crash.log")
+ # Initialize the FastCGI instance with the path to a crash log
+ # detailing unhandled exceptions (default RAILS_ROOT/log/fastcgi.crash.log)
+ # and the number of requests to process between garbage collection runs
+ # (default nil for normal GC behavior.) Optionally, pass a block which
+ # takes this instance as an argument for further configuration.
+ def initialize(log_file_path = nil, gc_request_period = nil)
@when_ready = nil
@processing = false
- trap("HUP", method(:restart_handler).to_proc)
- trap("USR1", method(:trap_handler).to_proc)
+ self.log_file_path = log_file_path || "#{RAILS_ROOT}/log/fastcgi.crash.log"
+ self.gc_request_period = gc_request_period
+
+ # Yield for additional configuration.
+ yield self if block_given?
- # initialize to 11 seconds ago to minimize special cases
+ # Safely install signal handlers.
+ install_signal_handlers
+
+ # Start error timestamp at 11 seconds ago.
@last_error_on = Time.now - 11
- @log_file_path = log_file_path
dispatcher_log(:info, "starting")
end
def process!
+ # Make a note of $" so we can safely reload this instance.
mark!
+ # Begin countdown to garbage collection.
+ run_gc! if gc_request_period
+
FCGI.each_cgi do |cgi|
- if when_ready == :restart
+ # Safely reload this instance if requested.
+ if when_ready == :reload
+ run_gc! if gc_request_period
restore!
@when_ready = nil
- dispatcher_log(:info, "restarted")
+ dispatcher_log(:info, "reloaded")
end
process_request(cgi)
+
+ # Break if graceful exit requested.
break if when_ready == :exit
+
+ # Garbage collection countdown.
+ if gc_request_period
+ @gc_request_countdown -= 1
+ run_gc! if @gc_request_countdown <= 0
+ end
end
+ GC.enable
dispatcher_log(:info, "terminated gracefully")
rescue SystemExit => exit_error
@@ -75,7 +111,19 @@ class RailsFCGIHandler
dispatcher_log(:error, error_message)
end
- def trap_handler(signal)
+ def install_signal_handlers
+ SIGNALS.each do |signal, handler_name|
+ install_signal_handler signal, method("#{handler_name}_handler").to_proc
+ end
+ end
+
+ def install_signal_handler(signal, handler)
+ trap signal, handler
+ rescue ArgumentError
+ dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
+ end
+
+ def graceful_exit_handler(signal)
if processing
dispatcher_log :info, "asked to terminate ASAP"
@when_ready = :exit
@@ -85,9 +133,9 @@ class RailsFCGIHandler
end
end
- def restart_handler(signal)
- @when_ready = :restart
- dispatcher_log :info, "asked to restart ASAP"
+ def reload_handler(signal)
+ @when_ready = :reload
+ dispatcher_log :info, "asked to reload ASAP"
end
def process_request(cgi)
@@ -109,4 +157,9 @@ class RailsFCGIHandler
Dispatcher.reset_application!
ActionController::Routing::Routes.reload
end
+
+ def run_gc!
+ @gc_request_countdown = gc_request_period
+ GC.enable; GC.start; GC.disable
+ end
end