Class: RailsFCGIHandler

Inherits:
Object show all
Defined in:
lib/fcgi_handler.rb

Constant Summary collapse

SIGNALS =
{
  'HUP'  => :reload,
  'TERM' => :graceful_exit,
  'USR1' => :graceful_exit
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(log_file_path = nil, gc_request_period = nil) {|_self| ... } ⇒ RailsFCGIHandler

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.

Yields:

  • (_self)

Yield Parameters:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fcgi_handler.rb', line 28

def initialize(log_file_path = nil, gc_request_period = nil)
  @when_ready = nil

  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?

  # Safely install signal handlers.
  install_signal_handlers

  # Start error timestamp at 11 seconds ago.
  @last_error_on = Time.now - 11

  dispatcher_log(:info, "starting")
end

Instance Attribute Details

#gc_request_periodObject

Returns the value of attribute gc_request_period.



15
16
17
# File 'lib/fcgi_handler.rb', line 15

def gc_request_period
  @gc_request_period
end

#log_file_pathObject

Returns the value of attribute log_file_path.



14
15
16
# File 'lib/fcgi_handler.rb', line 14

def log_file_path
  @log_file_path
end

#when_readyObject (readonly)

Returns the value of attribute when_ready.



12
13
14
# File 'lib/fcgi_handler.rb', line 12

def when_ready
  @when_ready
end

Class Method Details

.process!(*args, &block) ⇒ Object

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



19
20
21
# File 'lib/fcgi_handler.rb', line 19

def self.process!(*args, &block)
  new(*args, &block).process!
end

Instance Method Details

#process!(provider = FCGI) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/fcgi_handler.rb', line 46

def process!(provider = FCGI)
  # Make a note of $" so we can safely reload this instance.
  mark!

  # Begin countdown to garbage collection.
  run_gc! if gc_request_period

  provider.each_cgi do |cgi| 
    # Safely reload this instance if requested.
    if when_ready == :reload
      run_gc! if gc_request_period
      restore!
      @when_ready = nil
      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
  dispatcher_log(:info, "terminated by explicit exit")

rescue Object => fcgi_error
  # retry on errors that would otherwise have terminated the FCGI process,
  # but only if they occur more than 10 seconds apart.
  if !(SignalException === fcgi_error) && Time.now - @last_error_on > 10
    @last_error_on = Time.now
    dispatcher_error(fcgi_error, "almost killed by this error")
    retry
  else
    dispatcher_error(fcgi_error, "killed by this error")
  end
end