From: ahoward Date: 2003-02-13T00:03:12+09:00 Subject: class MOD_FCGI < FCGI rubyists- i've collected some usefull examples and added some signal handling to the fcgi package written by moon wolf. if any one has experience using fcgi out there i appreciate any comments. highlights are * reload any application using 'kill -HUP pid' w/o hanging apache * gracefull shutdown from confusing SIGUSR1/SIGHUP combo sent by apache/mod_fastcgi to fcgi programs * clean exit on 'kill -TERM pid' * each method which provides a CGI object eg of use MOD_FCGI.each('html3') do |cgi| content = '' cgi.env_table.each do |k,v| content << "#{k} -> #{v}
\n" end cgi.out { cgi.html { cgi.body { content } } } end ps. this is named MOD_FCGI because, AFAIK this signal handling is specific to apache's mod_fastcgi file : mod_fcgi.rb ----CUT---- require 'fcgi' require 'cgi' require 'ftools' class MOD_FCGI < FCGI class Log < File def tmpnam basename = nil, tmpdir = ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp' if $SAFE > 0 and tmpdir.tainted? tmpdir = '/tmp' end basename ||= File.basename $0 n = 0 while true begin path = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n) @_lock = path + '.lock' unless File.exist?(path) or File.exist?(@_lock) Dir.mkdir(@_lock) break end rescue raise "cannot generate tempfile `%s'" % path if n >= 16 end n += 1 end path end def initialize path = tmpnam, mode = 'w+', &block super path, mode, &block Dir.rmdir(@_lock) if defined? @_lock self.sync = true end end # enable CGI to bootstrap off of an FCGI request class CGI < ::CGI class << self def remove_params if (const_defined?(:CGI_PARAMS)) remove_const(:CGI_PARAMS) remove_const(:CGI_COOKIES) end end end def initialize(request, *args) self.class.remove_params @request = request super (*args) @args = *args end def args @args end def env_table @request.env end def stdinput @request.in end def stdoutput @request.out end end # initialize mod_fcgi @@handling_request = false @@exit_requested = false @@traps_installed = false @@signals = [] class << self def handle_request @@handling_request = true yield if block_given? ensure @@handling_request = false end def install_traps return if @@traps_installed # user signal to reload application # does a clean shutdown after which # the fcgi_pm will reload of source file trap ('SIGHUP') do unless @@signals.size > 0 @@signals << 'SIGHUP' if @@handling_request @@exit_requested = true else @@server.close exit end end end # sent from apache to do clean shutdown # note that a sigterm could be sent from fcgi_pm # AFTER this! we handle only one of them! trap ('SIGUSR1') do unless @@signals.size > 0 @@signals << 'SIGUSR1' if @@handling_request @@exit_requested = true else @@server.close exit end end end # see above note. # when no other signals pedning, simply exit quickly trap ('SIGTERM') do unless @@signals.size > 0 @@signals << 'SIGTERM' @@server.close exit end end # sent from mod_fcgi when client aborts request # we simply ignore this for now, although some smarts could be # added to abort the present request and resume accepting... trap ('SIGPIPE') do # nothing end @@traps_installed = true end def each (*args) install_traps while request = accept handle_request { if block_given? yield (CGI.new (request, *args)) request.finish end } exit if @@exit_requested end end alias each_request each end end ----CUT---- -a -- ==================================== | Ara Howard | NOAA Forecast Systems Laboratory | Information and Technology Services | Data Systems Group | R/FST 325 Broadway | Boulder, CO 80305-3328 | Email: ahoward@fsl.noaa.gov | Phone: 303-497-7238 | Fax: 303-497-7259 ====================================