Methods
Constants
SIGNALS = { 'HUP' => :reload, 'INT' => :exit_now, 'TERM' => :exit_now, 'USR1' => :exit, 'USR2' => :restart
GLOBAL_SIGNALS = SIGNALS.keys - %w(USR1)
Attributes
[RW] gc_request_period
[RW] log_file_path
[R] when_ready
Public Class methods
new(log_file_path = nil, gc_request_period = nil) {|self if block_given?| ...}

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.

    # File railties/lib/fcgi_handler.rb, line 31
31:   def initialize(log_file_path = nil, gc_request_period = nil)
32:     self.log_file_path = log_file_path || "#{RAILS_ROOT}/log/fastcgi.crash.log"
33:     self.gc_request_period = gc_request_period
34: 
35:     # Yield for additional configuration.
36:     yield self if block_given?
37: 
38:     # Safely install signal handlers.
39:     install_signal_handlers
40: 
41:     @app = Dispatcher.new
42: 
43:     # Start error timestamp at 11 seconds ago.
44:     @last_error_on = Time.now - 11
45:   end
process!(*args, &block)

Initialize and run the FastCGI instance, passing arguments through to new.

    # File railties/lib/fcgi_handler.rb, line 22
22:   def self.process!(*args, &block)
23:     new(*args, &block).process!
24:   end
Public Instance methods
process!(provider = FCGI)
    # File railties/lib/fcgi_handler.rb, line 47
47:   def process!(provider = FCGI)
48:     mark_features!
49: 
50:     dispatcher_log :info, 'starting'
51:     process_each_request provider
52:     dispatcher_log :info, 'stopping gracefully'
53: 
54:   rescue Exception => error
55:     case error
56:     when SystemExit
57:       dispatcher_log :info, 'stopping after explicit exit'
58:     when SignalException
59:       dispatcher_error error, 'stopping after unhandled signal'
60:     else
61:       # Retry if exceptions occur more than 10 seconds apart.
62:       if Time.now - @last_error_on > 10
63:         @last_error_on = Time.now
64:         dispatcher_error error, 'retrying after unhandled exception'
65:         retry
66:       else
67:         dispatcher_error error, 'stopping after unhandled exception within 10 seconds of the last'
68:       end
69:     end
70:   end
Protected Instance methods
close_connection(request)
     # File railties/lib/fcgi_handler.rb, line 236
236:     def close_connection(request)
237:       request.finish if request
238:     end
dispatcher_error(e, msg = "")
     # File railties/lib/fcgi_handler.rb, line 126
126:     def dispatcher_error(e, msg = "")
127:       error_message =
128:         "Dispatcher failed to catch: #{e} (#{e.class})\n" +
129:         "  #{e.backtrace.join("\n  ")}\n#{msg}"
130:       dispatcher_log(:error, error_message)
131:     end
dispatcher_log(level, msg)
     # File railties/lib/fcgi_handler.rb, line 118
118:     def dispatcher_log(level, msg)
119:       time_str = Time.now.strftime("%d/%b/%Y:%H:%M:%S")
120:       logger.send(level, "[#{time_str} :: #{$$}] #{msg}")
121:     rescue Exception => log_error  # Logger errors
122:       STDERR << "Couldn't write to #{@log_file_path.inspect}: #{msg}\n"
123:       STDERR << "  #{log_error.class}: #{log_error.message}\n"
124:     end
exit_handler(signal)
     # File railties/lib/fcgi_handler.rb, line 163
163:     def exit_handler(signal)
164:       dispatcher_log :info, "asked to stop ASAP"
165:       if @processing
166:         @when_ready = :exit
167:       else
168:         throw :exit
169:       end
170:     end
exit_now_handler(signal)
     # File railties/lib/fcgi_handler.rb, line 158
158:     def exit_now_handler(signal)
159:       dispatcher_log :info, "asked to stop immediately"
160:       exit
161:     end
gc_countdown()
     # File railties/lib/fcgi_handler.rb, line 228
228:     def gc_countdown
229:       if gc_request_period
230:         @gc_request_countdown ||= gc_request_period
231:         @gc_request_countdown -= 1
232:         run_gc! if @gc_request_countdown <= 0
233:       end
234:     end
install_signal_handler(signal, handler = nil)
     # File railties/lib/fcgi_handler.rb, line 137
137:     def install_signal_handler(signal, handler = nil)
138:       if SIGNALS.include?(signal) && self.class.method_defined?(name = "#{SIGNALS[signal]}_handler")
139:         handler ||= method(name).to_proc
140: 
141:         begin
142:           trap(signal, handler)
143:         rescue ArgumentError
144:           dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
145:         end
146:       else
147:         dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
148:       end
149:     end
install_signal_handlers()
     # File railties/lib/fcgi_handler.rb, line 133
133:     def install_signal_handlers
134:       GLOBAL_SIGNALS.each { |signal| install_signal_handler(signal) }
135:     end
logger()
     # File railties/lib/fcgi_handler.rb, line 114
114:     def logger
115:       @logger ||= Logger.new(@log_file_path)
116:     end
mark_features!()

Make a note of $" so we can safely reload this instance.

     # File railties/lib/fcgi_handler.rb, line 213
213:     def mark_features!
214:       @features = $".clone
215:     end
process_each_request(provider)
    # File railties/lib/fcgi_handler.rb, line 73
73:     def process_each_request(provider)
74:       request = nil
75: 
76:       catch :exit do
77:         provider.each do |request|
78:           process_request(request)
79: 
80:           case when_ready
81:             when :reload
82:               reload!
83:             when :restart
84:               close_connection(request)
85:               restart!
86:             when :exit
87:               close_connection(request)
88:               throw :exit
89:           end
90:         end
91:       end
92:     rescue SignalException => signal
93:       raise unless signal.message == 'SIGUSR1'
94:       close_connection(request)
95:     end
process_request(request)
     # File railties/lib/fcgi_handler.rb, line 97
 97:     def process_request(request)
 98:       @processing, @when_ready = true, nil
 99:       gc_countdown
100: 
101:       with_signal_handler 'USR1' do
102:         begin
103:           ::Rack::Handler::FastCGI.serve(request, @app)
104:         rescue SignalException, SystemExit
105:           raise
106:         rescue Exception => error
107:           dispatcher_error error, 'unhandled dispatch error'
108:         end
109:       end
110:     ensure
111:       @processing = false
112:     end
reload!()
     # File railties/lib/fcgi_handler.rb, line 205
205:     def reload!
206:       run_gc! if gc_request_period
207:       restore!
208:       @when_ready = nil
209:       dispatcher_log :info, "reloaded"
210:     end
reload_handler(signal)
     # File railties/lib/fcgi_handler.rb, line 172
172:     def reload_handler(signal)
173:       dispatcher_log :info, "asked to reload ASAP"
174:       if @processing
175:         @when_ready = :reload
176:       else
177:         reload!
178:       end
179:     end
restart!()
     # File railties/lib/fcgi_handler.rb, line 190
190:     def restart!
191:       config       = ::Config::CONFIG
192:       ruby         = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
193:       command_line = [ruby, $0, ARGV].flatten.join(' ')
194: 
195:       dispatcher_log :info, "restarted"
196: 
197:       # close resources as they won't be closed by
198:       # the OS when using exec
199:       logger.close rescue nil
200:       Rails.logger.close rescue nil
201: 
202:       exec(command_line)
203:     end
restart_handler(signal)
     # File railties/lib/fcgi_handler.rb, line 181
181:     def restart_handler(signal)
182:       dispatcher_log :info, "asked to restart ASAP"
183:       if @processing
184:         @when_ready = :restart
185:       else
186:         restart!
187:       end
188:     end
restore!()
     # File railties/lib/fcgi_handler.rb, line 217
217:     def restore!
218:       $".replace @features
219:       Dispatcher.reset_application!
220:       ActionController::Routing::Routes.reload
221:     end
run_gc!()
     # File railties/lib/fcgi_handler.rb, line 223
223:     def run_gc!
224:       @gc_request_countdown = gc_request_period
225:       GC.enable; GC.start; GC.disable
226:     end
with_signal_handler(signal) {|| ...}
     # File railties/lib/fcgi_handler.rb, line 151
151:     def with_signal_handler(signal)
152:       install_signal_handler(signal)
153:       yield
154:     ensure
155:       install_signal_handler(signal, 'DEFAULT')
156:     end