Skip to content

Commit

Permalink
Merged [5485] from trunk
Browse files Browse the repository at this point in the history
git-svn-id: http://svn-commit.rubyonrails.org/rails/branches/1-2-pre-release@5558 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
dhh committed Nov 18, 2006
1 parent ac22951 commit fb60a46
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
2 changes: 2 additions & 0 deletions railties/CHANGELOG
Expand Up @@ -10,6 +10,8 @@

* Add grep-based fallback to reaper, to work in pidless setups [Jamis Buck]

* Only wrap request processing with our USR1 signal handler so FastCGI can trap it and raise an exception while waiting for connections. Idle processes exit immediately rather than waiting for another request; active processes gracefully exit when the request is finished. [Jeremy Kemper]

* Alter prior change to use require_dependency instead of require_or_load. Causes ApplicationController to be reloaded again. Closes #6587. [Nicholas Seckar]

* Rake: use absolute paths to load lib and vendor tasks so they may be run outside of RAILS_ROOT. #6584 [jchris]
Expand Down
36 changes: 25 additions & 11 deletions railties/lib/fcgi_handler.rb
Expand Up @@ -6,11 +6,13 @@
class RailsFCGIHandler
SIGNALS = {
'HUP' => :reload,
'INT' => :exit_now,
'TERM' => :exit_now,
'USR1' => :exit,
'USR2' => :restart,
'SIGTRAP' => :breakpoint
}
GLOBAL_SIGNALS = SIGNALS.keys - %w(USR1)

attr_reader :when_ready

Expand Down Expand Up @@ -92,17 +94,23 @@ def dispatcher_error(e, msg = "")
end

def install_signal_handlers
SIGNALS.each do |signal, handler_name|
install_signal_handler(signal, method("#{handler_name}_handler").to_proc)
end
GLOBAL_SIGNALS.each { |signal| install_signal_handler(signal) }
end

def install_signal_handler(signal, handler)
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}."
end

def with_signal_handler(signal)
install_signal_handler(signal)
yield
ensure
install_signal_handler(signal, 'DEFAULT')
end

def exit_now_handler(signal)
dispatcher_log :info, "asked to terminate immediately"
exit
Expand All @@ -127,10 +135,13 @@ def breakpoint_handler(signal)
dispatcher_log :info, "asked to breakpoint ASAP"
@when_ready = :breakpoint
end

def process_each_request!(provider)
provider.each_cgi do |cgi|
process_request(cgi)
cgi = nil
provider.each_cgi do |cgi|
with_signal_handler 'USR1' do
process_request(cgi)
end

case when_ready
when :reload
Expand All @@ -148,6 +159,9 @@ def process_each_request!(provider)

gc_countdown
end
rescue SignalException => signal
raise unless signal.message == 'SIGUSR1'
close_connection(cgi) if cgi
end

def process_request(cgi)
Expand All @@ -161,7 +175,7 @@ def restart!
config = ::Config::CONFIG
ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
command_line = [ruby, $0, ARGV].flatten.join(' ')

dispatcher_log :info, "restarted"

exec(command_line)
Expand All @@ -183,7 +197,7 @@ def restore!
Dispatcher.reset_application!
ActionController::Routing::Routes.reload
end

def breakpoint!
require 'breakpoint'
port = defined?(BREAKPOINT_SERVER_PORT) ? BREAKPOINT_SERVER_PORT : 42531
Expand All @@ -197,14 +211,14 @@ def run_gc!
@gc_request_countdown = gc_request_period
GC.enable; GC.start; GC.disable
end

def gc_countdown
if 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
end
Expand Down

0 comments on commit fb60a46

Please sign in to comment.