Skip to content
This repository
Browse code

Yank FCGI Handler from core

  • Loading branch information...
commit 570f055c44a0b6da973f63689f8fedbef9fe32d3 1 parent 20d6938
Joshua Peek authored October 05, 2009
86  railties/lib/rails/commands/ncgi/listener
... ...
@@ -1,86 +0,0 @@
1  
-#!/usr/bin/env ruby
2  
-
3  
-require 'stringio'
4  
-require 'fileutils'
5  
-require 'fcgi_handler'
6  
-
7  
-def message(s)
8  
-  $stderr.puts "listener: #{s}" if ENV && ENV["DEBUG_GATEWAY"]
9  
-end
10  
-
11  
-class RemoteCGI < CGI
12  
-  attr_accessor :stdinput, :stdoutput, :env_table
13  
-  def initialize(env_table, input = nil, output = nil)
14  
-    self.env_table = env_table
15  
-    self.stdinput = input || StringIO.new
16  
-    self.stdoutput = output || StringIO.new
17  
-    super()
18  
-  end
19  
-
20  
-  def out(stream) # Ignore the requested output stream
21  
-    super(stdoutput)
22  
-  end
23  
-end
24  
-
25  
-class Listener
26  
-  include DRbUndumped
27  
-
28  
-  def initialize(timeout, socket_path)
29  
-    @socket = File.expand_path(socket_path)
30  
-    @mutex = Mutex.new
31  
-    @active = false
32  
-    @timeout = timeout
33  
-
34  
-    @handler = RailsFCGIHandler.new
35  
-    @handler.extend DRbUndumped
36  
-
37  
-    message 'opening socket'
38  
-    DRb.start_service("drbunix:#{@socket}", self)
39  
-
40  
-    message 'entering process loop'
41  
-    @handler.process! self
42  
-  end
43  
-
44  
-  def each_cgi(&cgi_block)
45  
-    @cgi_block = cgi_block
46  
-    message 'entering idle loop'
47  
-    loop do
48  
-      sleep @timeout rescue nil
49  
-      die! unless @active
50  
-      @active = false
51  
-    end
52  
-  end
53  
-
54  
-  def process(env, input)
55  
-    message 'received request'
56  
-    @mutex.synchronize do
57  
-      @active = true
58  
-
59  
-      message 'creating input stream'
60  
-      input_stream = StringIO.new(input)
61  
-      message 'building CGI instance'
62  
-      cgi = RemoteCGI.new(eval(env), input_stream)
63  
-
64  
-      message 'yielding to fcgi handler'
65  
-      @cgi_block.call cgi
66  
-      message 'yield finished -- sending output'
67  
-
68  
-      cgi.stdoutput.seek(0)
69  
-      output = cgi.stdoutput.read
70  
-
71  
-      return output
72  
-    end
73  
-  end
74  
-
75  
-  def die!
76  
-    message 'shutting down'
77  
-    DRb.stop_service
78  
-    FileUtils.rm_f @socket
79  
-    Kernel.exit 0
80  
-  end
81  
-end
82  
-
83  
-socket_path = ARGV.shift
84  
-timeout = (ARGV.shift || 90).to_i
85  
-
86  
-Listener.new(timeout, socket_path)
241  railties/lib/rails/fcgi_handler.rb
... ...
@@ -1,241 +0,0 @@
1  
-require 'fcgi'
2  
-require 'logger'
3  
-require 'rails/dispatcher'
4  
-require 'rbconfig'
5  
-
6  
-class RailsFCGIHandler
7  
-  SIGNALS = {
8  
-    'HUP'     => :reload,
9  
-    'INT'     => :exit_now,
10  
-    'TERM'    => :exit_now,
11  
-    'USR1'    => :exit,
12  
-    'USR2'    => :restart
13  
-  }
14  
-  GLOBAL_SIGNALS = SIGNALS.keys - %w(USR1)
15  
-
16  
-  attr_reader :when_ready
17  
-
18  
-  attr_accessor :log_file_path
19  
-  attr_accessor :gc_request_period
20  
-
21  
-  # Initialize and run the FastCGI instance, passing arguments through to new.
22  
-  def self.process!(*args, &block)
23  
-    new(*args, &block).process!
24  
-  end
25  
-
26  
-  # Initialize the FastCGI instance with the path to a crash log
27  
-  # detailing unhandled exceptions (default RAILS_ROOT/log/fastcgi.crash.log)
28  
-  # and the number of requests to process between garbage collection runs
29  
-  # (default nil for normal GC behavior.)  Optionally, pass a block which
30  
-  # takes this instance as an argument for further configuration.
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
46  
-
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
71  
-
72  
-  protected
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
96  
-
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
113  
-
114  
-    def logger
115  
-      @logger ||= Logger.new(@log_file_path)
116  
-    end
117  
-
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
125  
-
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
132  
-
133  
-    def install_signal_handlers
134  
-      GLOBAL_SIGNALS.each { |signal| install_signal_handler(signal) }
135  
-    end
136  
-
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
150  
-
151  
-    def with_signal_handler(signal)
152  
-      install_signal_handler(signal)
153  
-      yield
154  
-    ensure
155  
-      install_signal_handler(signal, 'DEFAULT')
156  
-    end
157  
-
158  
-    def exit_now_handler(signal)
159  
-      dispatcher_log :info, "asked to stop immediately"
160  
-      exit
161  
-    end
162  
-
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
171  
-
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
180  
-
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
189  
-
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
204  
-
205  
-    def reload!
206  
-      run_gc! if gc_request_period
207  
-      restore!
208  
-      @when_ready = nil
209  
-      dispatcher_log :info, "reloaded"
210  
-    end
211  
-
212  
-    # Make a note of $" so we can safely reload this instance.
213  
-    def mark_features!
214  
-      @features = $".clone
215  
-    end
216  
-
217  
-    def restore!
218  
-      $".replace @features
219  
-      # TODO: Reloading the application should be the "Application"s
220  
-      # responsibility
221  
-      ActionDispatch::Callbacks.new(lambda {}, true)
222  
-      ActionController::Routing::Routes.reload
223  
-    end
224  
-
225  
-    def run_gc!
226  
-      @gc_request_countdown = gc_request_period
227  
-      GC.enable; GC.start; GC.disable
228  
-    end
229  
-
230  
-    def gc_countdown
231  
-      if gc_request_period
232  
-        @gc_request_countdown ||= gc_request_period
233  
-        @gc_request_countdown -= 1
234  
-        run_gc! if @gc_request_countdown <= 0
235  
-      end
236  
-    end
237  
-
238  
-    def close_connection(request)
239  
-      request.finish if request
240  
-    end
241  
-end
16  railties/lib/rails/generators/rails/app/app_generator.rb
@@ -18,9 +18,6 @@ class AppGenerator < Base
18 18
     class_option :template, :type => :string, :aliases => "-m",
19 19
                             :desc => "Path to an application template (can be a filesystem path or URL)."
20 20
 
21  
-    class_option :with_dispatchers, :type => :boolean, :aliases => "-D", :default => false,
22  
-                                    :desc => "Add CGI/FastCGI/mod_ruby dispatchers code"
23  
-
24 21
     class_option :skip_activerecord, :type => :boolean, :aliases => "-O", :default => false,
25 22
                                    :desc => "Skip ActiveRecord files"
26 23
 
@@ -113,19 +110,6 @@ def create_public_files
113 110
       directory "public", "public", :recursive => false # Do small steps, so anyone can overwrite it.
114 111
     end
115 112
 
116  
-    def create_dispatch_files
117  
-      return unless options[:with_dispatchers]
118  
-
119  
-      template "dispatchers/dispatch.rb", "public/dispatch.rb"
120  
-      chmod "public/dispatch.rb", 0755, :verbose => false
121  
-
122  
-      template "dispatchers/dispatch.rb", "public/dispatch.cgi"
123  
-      chmod "public/dispatch.cgi", 0755, :verbose => false
124  
-
125  
-      template "dispatchers/dispatch.fcgi", "public/dispatch.fcgi"
126  
-      chmod "public/dispatch.fcgi", 0755, :verbose => false
127  
-    end
128  
-
129 113
     def create_public_image_files
130 114
       directory "public/images"
131 115
     end
24  railties/lib/rails/generators/rails/app/templates/dispatchers/dispatch.fcgi
... ...
@@ -1,24 +0,0 @@
1  
-<%= shebang %>
2  
-#
3  
-# You may specify the path to the FastCGI crash log (a log of unhandled
4  
-# exceptions which forced the FastCGI instance to exit, great for debugging)
5  
-# and the number of requests to process before running garbage collection.
6  
-#
7  
-# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
8  
-# and the GC period is nil (turned off).  A reasonable number of requests
9  
-# could range from 10-100 depending on the memory footprint of your app.
10  
-#
11  
-# Example:
12  
-#   # Default log path, normal GC behavior.
13  
-#   RailsFCGIHandler.process!
14  
-#
15  
-#   # Default log path, 50 requests between GC.
16  
-#   RailsFCGIHandler.process! nil, 50
17  
-#
18  
-#   # Custom log path, normal GC behavior.
19  
-#   RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
20  
-#
21  
-require File.dirname(__FILE__) + "/../config/environment"
22  
-require 'fcgi_handler'
23  
-
24  
-RailsFCGIHandler.process!
10  railties/lib/rails/generators/rails/app/templates/dispatchers/dispatch.rb
... ...
@@ -1,10 +0,0 @@
1  
-<%= shebang %>
2  
-
3  
-require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
4  
-
5  
-# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
6  
-# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
7  
-require "dispatcher"
8  
-
9  
-ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
10  
-Dispatcher.dispatch
97  railties/lib/rails/generators/rails/app/templates/dispatchers/gateway.cgi
... ...
@@ -1,97 +0,0 @@
1  
-<%= shebang %>
2  
-
3  
-require 'drb'
4  
-
5  
-# This file includes an experimental gateway CGI implementation. It will work
6  
-# only on platforms which support both fork and sockets.
7  
-#
8  
-# To enable it edit public/.htaccess and replace dispatch.cgi with gateway.cgi.
9  
-#
10  
-# Next, create the directory log/drb_gateway and grant the apache user rw access
11  
-# to said directory.
12  
-#
13  
-# On the next request to your server, the gateway tracker should start up, along
14  
-# with a few listener processes. This setup should provide you with much better
15  
-# speeds than dispatch.cgi.
16  
-#
17  
-# Keep in mind that the first request made to the server will be slow, as the
18  
-# tracker and listeners will have to load. Also, the tracker and listeners will
19  
-# shutdown after a period if inactivity. You can set this value below -- the
20  
-# default is 90 seconds.
21  
-
22  
-TrackerSocket = File.expand_path(File.join(File.dirname(__FILE__), '../log/drb_gateway/tracker.sock'))
23  
-DieAfter = 90 # Seconds
24  
-Listeners = 3
25  
-
26  
-def message(s)
27  
-  $stderr.puts "gateway.cgi: #{s}" if ENV && ENV["DEBUG_GATEWAY"]
28  
-end
29  
-
30  
-def listener_socket(number)
31  
-  File.expand_path(File.join(File.dirname(__FILE__), "../log/drb_gateway/listener_#{number}.sock"))
32  
-end
33  
-
34  
-unless File.exist? TrackerSocket
35  
-  message "Starting tracker and #{Listeners} listeners"
36  
-  fork do
37  
-    Process.setsid
38  
-    STDIN.reopen "/dev/null"
39  
-    STDOUT.reopen "/dev/null", "a"
40  
-
41  
-    root = File.expand_path(File.dirname(__FILE__) + '/..')
42  
-
43  
-    message "starting tracker"
44  
-    fork do
45  
-      ARGV.clear
46  
-      ARGV << TrackerSocket << Listeners.to_s << DieAfter.to_s
47  
-      load File.join(root, 'script', 'tracker')
48  
-    end
49  
-
50  
-    message "starting listeners"
51  
-    require File.join(root, 'config/environment.rb')
52  
-    Listeners.times do |number|
53  
-      fork do
54  
-        ARGV.clear
55  
-        ARGV << listener_socket(number) << DieAfter.to_s
56  
-        load File.join(root, 'script', 'listener')
57  
-      end
58  
-    end
59  
-  end
60  
-
61  
-  message "waiting for tracker and listener to arise..."
62  
-  ready = false
63  
-  10.times do
64  
-    sleep 0.5
65  
-    break if (ready = File.exist?(TrackerSocket) && File.exist?(listener_socket(0)))
66  
-  end
67  
-
68  
-  if ready
69  
-    message "tracker and listener are ready"
70  
-  else
71  
-    message "Waited 5 seconds, listener and tracker not ready... dropping request"
72  
-    Kernel.exit 1
73  
-  end
74  
-end
75  
-
76  
-DRb.start_service
77  
-
78  
-message "connecting to tracker"
79  
-tracker = DRbObject.new_with_uri("drbunix:#{TrackerSocket}")
80  
-
81  
-input = $stdin.read
82  
-$stdin.close
83  
-
84  
-env = ENV.inspect
85  
-
86  
-output = nil
87  
-tracker.with_listener do |number|
88  
-  message "connecting to listener #{number}"
89  
-  socket = listener_socket(number)
90  
-  listener = DRbObject.new_with_uri("drbunix:#{socket}")
91  
-  output = listener.process(env, input)
92  
-  message "listener #{number} has finished, writing output"
93  
-end
94  
-
95  
-$stdout.write output
96  
-$stdout.flush
97  
-$stdout.close
5  railties/lib/rails/tasks/framework.rake
@@ -110,11 +110,6 @@ namespace :rails do
110 110
       invoke_from_app_generator :create_prototype_files
111 111
     end
112 112
 
113  
-    desc "Generate dispatcher files in RAILS_ROOT/public"
114  
-    task :generate_dispatchers do
115  
-      invoke_from_app_generator :create_dispatch_files
116  
-    end
117  
-
118 113
     desc "Add new scripts to the application script/ directory"
119 114
     task :scripts do
120 115
       invoke_from_app_generator :create_script_files
290  railties/test/application/fcgi_dispatcher_test.rb
... ...
@@ -1,290 +0,0 @@
1  
-require 'isolation/abstract_unit'
2  
-require 'mocha'
3  
-
4  
-begin
5  
-
6  
-begin
7  
-  require 'fcgi'
8  
-rescue LoadError
9  
-  gem 'fcgi', '0.8.7'
10  
-  require 'fcgi'
11  
-end
12  
-
13  
-class RailsFCGIHandlerTest < Test::Unit::TestCase
14  
-  include ActiveSupport::Testing::Isolation
15  
-
16  
-  def setup
17  
-    build_app
18  
-    boot_rails
19  
-
20  
-    require "#{rails_root}/config/environment"
21  
-    require 'rails/fcgi_handler'
22  
-
23  
-    @log = StringIO.new
24  
-    @handler = RailsFCGIHandler.new(@log)
25  
-  end
26  
-
27  
-  def test_process_restart
28  
-    request = mock
29  
-    FCGI.stubs(:each).yields(request)
30  
-
31  
-    @handler.expects(:process_request).once
32  
-    @handler.expects(:dispatcher_error).never
33  
-
34  
-    @handler.expects(:when_ready).returns(:restart)
35  
-    @handler.expects(:close_connection).with(request)
36  
-    @handler.expects(:reload!).never
37  
-    @handler.expects(:restart!)
38  
-
39  
-    @handler.process!
40  
-  end
41  
-
42  
-  def test_process_exit
43  
-    request = mock
44  
-    FCGI.stubs(:each).yields(request)
45  
-
46  
-    @handler.expects(:process_request).once
47  
-    @handler.expects(:dispatcher_error).never
48  
-
49  
-    @handler.expects(:when_ready).returns(:exit)
50  
-    @handler.expects(:close_connection).with(request)
51  
-    @handler.expects(:reload!).never
52  
-    @handler.expects(:restart!).never
53  
-
54  
-    @handler.process!
55  
-  end
56  
-
57  
-  def test_process_with_system_exit_exception
58  
-    request = mock
59  
-    FCGI.stubs(:each).yields(request)
60  
-
61  
-    @handler.expects(:process_request).once.raises(SystemExit)
62  
-    @handler.stubs(:dispatcher_log)
63  
-    @handler.expects(:dispatcher_log).with(:info, regexp_matches(/^stopping/))
64  
-    @handler.expects(:dispatcher_error).never
65  
-
66  
-    @handler.expects(:when_ready).never
67  
-    @handler.expects(:close_connection).never
68  
-    @handler.expects(:reload!).never
69  
-    @handler.expects(:restart!).never
70  
-
71  
-    @handler.process!
72  
-  end
73  
-
74  
-  def test_restart_handler_outside_request
75  
-    @handler.expects(:dispatcher_log).with(:info, "asked to restart ASAP")
76  
-    @handler.expects(:restart!).once
77  
-
78  
-    @handler.send(:restart_handler, nil)
79  
-    assert_equal nil, @handler.when_ready
80  
-  end
81  
-
82  
-  def test_install_signal_handler_should_log_on_bad_signal
83  
-    @handler.stubs(:trap).raises(ArgumentError)
84  
-
85  
-    @handler.expects(:dispatcher_log).with(:warn, "Ignoring unsupported signal CHEESECAKE.")
86  
-    @handler.send(:install_signal_handler, "CHEESECAKE", nil)
87  
-  end
88  
-
89  
-  def test_reload
90  
-    @handler.expects(:restore!)
91  
-    @handler.expects(:dispatcher_log).with(:info, "reloaded")
92  
-
93  
-    @handler.send(:reload!)
94  
-    assert_nil @handler.when_ready
95  
-  end
96  
-
97  
-  def test_reload_runs_gc_when_gc_request_period_set
98  
-    @handler.expects(:run_gc!)
99  
-    @handler.expects(:restore!)
100  
-    @handler.expects(:dispatcher_log).with(:info, "reloaded")
101  
-    @handler.gc_request_period = 10
102  
-    @handler.send(:reload!)
103  
-  end
104  
-
105  
-  def test_reload_doesnt_run_gc_if_gc_request_period_isnt_set
106  
-    @handler.expects(:run_gc!).never
107  
-    @handler.expects(:restore!)
108  
-    @handler.expects(:dispatcher_log).with(:info, "reloaded")
109  
-    @handler.send(:reload!)
110  
-  end
111  
-
112  
-  def test_restart!
113  
-    @handler.expects(:dispatcher_log).with(:info, "restarted")
114  
-    @handler.expects(:exec).returns('restarted')
115  
-    assert_equal 'restarted', @handler.send(:restart!)
116  
-  end
117  
-
118  
-  def test_restore!
119  
-    $".expects(:replace)
120  
-    ActionController::Routing::Routes.expects(:reload)
121  
-    @handler.send(:restore!)
122  
-  end
123  
-
124  
-  def test_uninterrupted_processing
125  
-    request = mock
126  
-    FCGI.expects(:each).yields(request)
127  
-    @handler.expects(:process_request).with(request)
128  
-
129  
-    @handler.process!
130  
-
131  
-    assert_nil @handler.when_ready
132  
-  end
133  
-end
134  
-
135  
-class RailsFCGIHandlerSignalsTest < Test::Unit::TestCase
136  
-  include ActiveSupport::Testing::Isolation
137  
-
138  
-  def setup
139  
-    build_app
140  
-    boot_rails
141  
-
142  
-    require "#{rails_root}/config/environment"
143  
-    require 'rails/fcgi_handler'
144  
-
145  
-    ::RailsFCGIHandler.class_eval do
146  
-      attr_accessor :signal
147  
-      alias_method :old_gc_countdown, :gc_countdown
148  
-      def gc_countdown
149  
-        signal ? Process.kill(signal, $$) : old_gc_countdown
150  
-      end
151  
-    end
152  
-
153  
-    @log = StringIO.new
154  
-    @handler = RailsFCGIHandler.new(@log)
155  
-    @dispatcher = mock
156  
-    Dispatcher.stubs(:new).returns(@dispatcher)
157  
-  end
158  
-
159  
-  def test_interrupted_via_HUP_when_not_in_request
160  
-    request = mock
161  
-    FCGI.expects(:each).once.yields(request)
162  
-    @handler.expects(:signal).times(2).returns('HUP')
163  
-
164  
-    @handler.expects(:reload!).once
165  
-    @handler.expects(:close_connection).never
166  
-    @handler.expects(:exit).never
167  
-
168  
-    @handler.process!
169  
-    assert_equal :reload, @handler.when_ready
170  
-  end
171  
-
172  
-  def test_interrupted_via_USR1_when_not_in_request
173  
-    request = mock
174  
-    FCGI.expects(:each).once.yields(request)
175  
-    @handler.expects(:signal).times(2).returns('USR1')
176  
-    @handler.expects(:exit_handler).never
177  
-
178  
-    @handler.expects(:reload!).never
179  
-    @handler.expects(:close_connection).with(request).once
180  
-    @handler.expects(:exit).never
181  
-
182  
-    @handler.process!
183  
-    assert_nil @handler.when_ready
184  
-  end
185  
-
186  
-  def test_restart_via_USR2_when_in_request
187  
-    request = mock
188  
-    FCGI.expects(:each).once.yields(request)
189  
-    @handler.expects(:signal).times(2).returns('USR2')
190  
-    @handler.expects(:exit_handler).never
191  
-
192  
-    @handler.expects(:reload!).never
193  
-    @handler.expects(:close_connection).with(request).once
194  
-    @handler.expects(:exit).never
195  
-    @handler.expects(:restart!).once
196  
-
197  
-    @handler.process!
198  
-    assert_equal :restart, @handler.when_ready
199  
-  end
200  
-
201  
-  def test_interrupted_via_TERM
202  
-    request = mock
203  
-    FCGI.expects(:each).once.yields(request)
204  
-    ::Rack::Handler::FastCGI.expects(:serve).once.returns('TERM')
205  
-
206  
-    @handler.expects(:reload!).never
207  
-    @handler.expects(:close_connection).never
208  
-
209  
-    @handler.process!
210  
-    assert_nil @handler.when_ready
211  
-  end
212  
-
213  
-  def test_runtime_exception_in_fcgi
214  
-    error = RuntimeError.new('foo')
215  
-    FCGI.expects(:each).times(2).raises(error)
216  
-    @handler.expects(:dispatcher_error).with(error, regexp_matches(/^retrying/))
217  
-    @handler.expects(:dispatcher_error).with(error, regexp_matches(/^stopping/))
218  
-    @handler.process!
219  
-  end
220  
-
221  
-  def test_runtime_error_in_dispatcher
222  
-    request = mock
223  
-    error = RuntimeError.new('foo')
224  
-    FCGI.expects(:each).once.yields(request)
225  
-    ::Rack::Handler::FastCGI.expects(:serve).once.raises(error)
226  
-    @handler.expects(:dispatcher_error).with(error, regexp_matches(/^unhandled/))
227  
-    @handler.process!
228  
-  end
229  
-
230  
-  def test_signal_exception_in_fcgi
231  
-    error = SignalException.new('USR2')
232  
-    FCGI.expects(:each).once.raises(error)
233  
-    @handler.expects(:dispatcher_error).with(error, regexp_matches(/^stopping/))
234  
-    @handler.process!
235  
-  end
236  
-
237  
-  def test_signal_exception_in_dispatcher
238  
-    request = mock
239  
-    error = SignalException.new('USR2')
240  
-    FCGI.expects(:each).once.yields(request)
241  
-    ::Rack::Handler::FastCGI.expects(:serve).once.raises(error)
242  
-    @handler.expects(:dispatcher_error).with(error, regexp_matches(/^stopping/))
243  
-    @handler.process!
244  
-  end
245  
-end
246  
-
247  
-class RailsFCGIHandlerPeriodicGCTest < Test::Unit::TestCase
248  
-  include ActiveSupport::Testing::Isolation
249  
-
250  
-  def setup
251  
-    build_app
252  
-    boot_rails
253  
-
254  
-    require "#{rails_root}/config/environment"
255  
-    require 'rails/fcgi_handler'
256  
-
257  
-    @log = StringIO.new
258  
-  end
259  
-
260  
-  def teardown
261  
-    GC.enable
262  
-  end
263  
-
264  
-  def test_normal_gc
265  
-    @handler = RailsFCGIHandler.new(@log)
266  
-    assert_nil @handler.gc_request_period
267  
-
268  
-    # When GC is enabled, GC.disable disables and returns false.
269  
-    assert_equal false, GC.disable
270  
-  end
271  
-
272  
-  def test_periodic_gc
273  
-    @handler = RailsFCGIHandler.new(@log, 10)
274  
-    assert_equal 10, @handler.gc_request_period
275  
-
276  
-    request = mock
277  
-    FCGI.expects(:each).times(10).yields(request)
278  
-
279  
-    @handler.expects(:run_gc!).never
280  
-    9.times { @handler.process! }
281  
-    @handler.expects(:run_gc!).once
282  
-    @handler.process!
283  
-
284  
-    assert_nil @handler.when_ready
285  
-  end
286  
-end
287  
-
288  
-rescue LoadError
289  
-  $stderr.puts 'Skipping fcgi tests. `gem install fcgi` and try again.'
290  
-end
12  railties/test/generators/app_generator_test.rb
@@ -53,18 +53,6 @@ def test_invalid_database_option_raises_an_error
53 53
     assert_match /Invalid value for \-\-database option/, content
54 54
   end
55 55
 
56  
-  def test_dispatchers_are_not_added_by_default
57  
-    run_generator
58  
-    assert_no_file "public/dispatch.cgi"
59  
-    assert_no_file "public/dispatch.fcgi"
60  
-  end
61  
-
62  
-  def test_dispatchers_are_added_if_required
63  
-    run_generator ["--with-dispatchers"]
64  
-    assert_file "public/dispatch.cgi"
65  
-    assert_file "public/dispatch.fcgi"
66  
-  end
67  
-
68 56
   def test_config_database_is_added_by_default
69 57
     run_generator
70 58
     assert_file "config/database.yml", /sqlite3/

0 notes on commit 570f055

Please sign in to comment.
Something went wrong with that request. Please try again.