Class: SCGI::Processor

Inherits:
Monitor
  • Object
show all
Defined in:
lib/scgi.rb

Overview

This is the complete guts of the SCGI system. It is designed so that people can take it and implement it for their own systems, not just Ruby on Rails. This implementation is not complete since you must create your own that implements the process_request method.

The SCGI protocol only works with TCP/IP sockets and not domain sockets. It might be useful for shared hosting people to have domain sockets, but they aren’t supported in Apache, and in lighttpd they’re unreliable. Also, domain sockets don’t work so well on Windows.

Available settings: :socket => Use this socket :host => Create a socket bound to this IP (if :port is also used) :port => Create a socket bound to this IP (if :host is also used) :log => Use this logger instead of creating one :logfile => Use this logfile instead of log/scgi.log :maxconns => Allow this many max connections, more than this are redirected

to /busy.html (default: 2**30 - 1)

Instance Method Summary collapse

Constructor Details

#initialize(settings = {}) ⇒ Processor

Returns a new instance of Processor.



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/scgi.rb', line 94

def initialize(settings = {})
  @socket ||= settings[:socket] || (TCPServer.new(settings[:host], settings[:port]) if settings[:host] && settings[:port])
  @total_conns ||= 0
  @shutdown ||= false
  @dead ||= false
  @threads ||= Queue.new
  @log ||= settings[:log] || LogFactory.instance.create(settings[:logfile] || 'log/scgi.log')
  @maxconns ||= settings[:maxconns] || 2**30-1
  super()
  setup_signals
end

Instance Method Details

#listen(socket = nil) ⇒ Object

Starts the SCGI::Processor having it listen on the given socket, if one is provided, or the one established in new, if not. This function does not return until a shutdown.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/scgi.rb', line 109

def listen(socket = nil)
  @socket ||= socket
  
  # we also need a small collector thread that does nothing
  # but pull threads off the thread queue and joins them
  @collector = Thread.new do
    while t = @threads.shift
      collect_thread(t)
      @total_conns += 1
    end
  end
    
  thread = Thread.new do
    loop do
      handle_client(@socket.accept)
      break if @shutdown and @threads.length <= 0
    end
  end
    
  # and then collect the listener thread which blocks until it exits
  collect_thread(thread)
  
  @socket.close unless @socket.closed?
  @dead = true
  @log.info("Exited accept loop. Shutdown complete.")
end

#shutdown(force = false) ⇒ Object

When called it will set the @shutdown flag indicating to the SCGI::Processor.listen function that all new connections should be set to /busy.html, and all current connections should be “valved” off. Once all the current connections are gone the SCGI::Processor.listen function will exit.

Use the force=true parameter to force an immediate shutdown. This is done by closing the listening socket, so it’s rather violent.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/scgi.rb', line 145

def shutdown(force = false)
  synchronize do
    @shutdown = true
    
    if @threads.length == 0 
      @log.info("Immediate shutdown since nobody is connected.")
      @socket.close
    elsif force
      @log.info("Forcing shutdown.  You may see exceptions.")
      @socket.close
    else
      @log.info("Shutdown requested.  Beginning graceful shutdown with #{@threads.length} connected.")
    end
  end
end