Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merged [5485] from trunk

git-svn-id: http://svn-commit.rubyonrails.org/rails/branches/1-2-pre-release@5558 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit fb60a469c023baa89157b325b5ddc4e8ae29693d 1 parent ac22951
@dhh dhh authored
Showing with 27 additions and 11 deletions.
  1. +2 −0  railties/CHANGELOG
  2. +25 −11 railties/lib/fcgi_handler.rb
View
2  railties/CHANGELOG
@@ -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]
View
36 railties/lib/fcgi_handler.rb
@@ -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
@@ -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
@@ -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
@@ -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)
@@ -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)
@@ -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
@@ -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
Please sign in to comment.
Something went wrong with that request. Please try again.