class Thin::Preforker::Controller
Public Class Methods
new(options)
click to toggle source
# File lib/thin/preforker/controller.rb, line 4 def initialize options @options = options if @options[:socket] @options.delete(:address) @options.delete(:port) end GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=) end
Public Instance Methods
restart()
click to toggle source
Stop and start the servers.
# File lib/thin/preforker/controller.rb, line 98 def restart daemonize_prefoker if @options[:daemonize] with_each_server do |n| stop_server n start_server n, app sleep 0.1 # Let the OS breath end Process.waitall end
start()
click to toggle source
Start the servers
# File lib/thin/preforker/controller.rb, line 16 def start daemonize_prefoker if @options[:daemonize] with_each_server do |n| start_server n, app end Process.waitall end
start_server(number, app)
click to toggle source
Start a single server
# File lib/thin/preforker/controller.rb, line 27 def start_server(number, app) log "Starting server on #{server_id(number)} ... " server = Thin::Server.new(server_options_for(number)[:socket] || server_options_for(number)[:address], server_options_for(number)[:port], server_options_for(number)) # Set options server.pid_file = server_options_for(number)[:pid] server.log_file = server_options_for(number)[:log] server.timeout = server_options_for(number)[:timeout] server.maximum_connections = server_options_for(number)[:max_conns] server.maximum_persistent_connections = server_options_for(number)[:max_persistent_conns] server.threaded = server_options_for(number)[:threaded] server.no_epoll = server_options_for(number)[:no_epoll] if server.backend.respond_to?(:no_epoll=) # ssl support if server_options_for(number)[:ssl] server.ssl = true server.ssl_options = { :private_key_file => server_options_for(number)[:ssl_key_file], :cert_chain_file => server_options_for(number)[:ssl_cert_file], :verify_peer => server_options_for(number)[:ssl_verify] } end before_fork_for(server, number) Process.fork do after_fork_for(server, number) # Constantize backend class server_options_for(number)[:backend] = eval(server_options_for(number)[:backend], TOPLEVEL_BINDING) if server_options_for(number)[:backend] # +config+ must be called before changing privileges since it might require superuser power. server.config server.change_privilege server_options_for(number)[:user], server_options_for(number)[:group] if server_options_for(number)[:user] && server_options_for(number)[:group] # Set app already loaded server.app = app # If a prefix is required, wrap in Rack URL mapper server.app = Rack::URLMap.new(server_options_for(number)[:prefix] => server.app) if server_options_for(number)[:prefix] # If a stats URL is specified, wrap in Stats adapter server.app = Thin::Stats::Adapter.new(server.app, server_options_for(number)[:stats]) if server_options_for(number)[:stats] server.start end wait_for_file :creation, server_options_for(number)[:pid] end
stop()
click to toggle source
Stop the servers
# File lib/thin/preforker/controller.rb, line 78 def stop with_each_server do |n| stop_server n end end
stop_server(number)
click to toggle source
Stop a single server
# File lib/thin/preforker/controller.rb, line 85 def stop_server(number) log "Stopping server on #{server_id(number)} ... " raise Thin::OptionRequired, :pid unless @options[:pid] tail_log(server_options_for(number)[:log]) do if Server.kill(server_options_for(number)[:pid], server_options_for(number)[:force] ? 0 : (server_options_for(number)[:timeout] || 60)) wait_for_file :deletion, server_options_for(number)[:pid] end end end
Private Instance Methods
after_fork_for(server, number)
click to toggle source
# File lib/thin/preforker/controller.rb, line 169 def after_fork_for(server, number) log_fp = open(server_options_for(number)[:log], "a") log_fp.sync = true $stdout.reopen(log_fp) $stderr.reopen(log_fp) $stdin.reopen("/dev/null") $0 = server.name Dir.chdir(@pwd) server.send(:write_pid_file) server.send(:at_exit) do log ">> Exiting!" server.send(:remove_pid_file) end Signal.trap("INT") { server.stop! } Signal.trap("TERM") { server.stop } Signal.trap("QUIT") { server.stop } unless Thin.win? ObjectSpace.each_object(File) { |fp| fp.reopen(fp.path, "a") if @logs.include? fp.path } callbacks.run_after_fork_callbacks server, number end
app()
click to toggle source
# File lib/thin/preforker/controller.rb, line 111 def app # If a Rack config file is specified we eval it inside a Rack::Builder block to create # a Rack adapter from it. Or else we guess which adapter to use and load it. @app ||= @options[:rackup] ? load_rackup_config : load_adapter end
before_fork_for(server, number)
click to toggle source
# File lib/thin/preforker/controller.rb, line 152 def before_fork_for(server, number) raise ArgumentError, "You must specify a pid file to fork" unless server_options_for(number)[:pid] raise ArgumentError, "You must specify a log file to fork" unless server_options_for(number)[:log] server.send(:remove_stale_pid_file) @pwd = Dir.pwd # Current directory is changed during fork, so store it FileUtils.mkdir_p File.dirname(server_options_for(number)[:pid]) FileUtils.mkdir_p File.dirname(server_options_for(number)[:log]) @logs = [] ObjectSpace.each_object(File) { |fp| @logs << fp.path if fp.fcntl(Fcntl::F_GETFL) == File::APPEND | File::WRONLY rescue false } callbacks.run_before_fork_callbacks server, number end
callbacks()
click to toggle source
# File lib/thin/preforker/controller.rb, line 117 def callbacks @callbacks ||= Callbacks.new @options[:callbacks] end
daemonize_prefoker()
click to toggle source
# File lib/thin/preforker/controller.rb, line 195 def daemonize_prefoker raise ArgumentError, "You must specify a preforker pid file to daemonize" unless @options[:preforker_pid] raise ArgumentError, "You must specify a preforker log file to daemonize" unless @options[:preforker_log] pwd = Dir.pwd # Current directory is changed during fork, so store it FileUtils.mkdir_p File.dirname(@options[:preforker_pid]) FileUtils.mkdir_p File.dirname(@options[:preforker_log]) Daemonize.daemonize @options[:preforker_log], "thin-preforker" Dir.chdir(pwd) Daemonize.redirect_io @options[:preforker_log] log ">> Writing PID to #{@options[:preforker_pid]}" open(@options[:preforker_pid],"w") { |f| f.write(Process.pid) } File.chmod(0644, @options[:preforker_pid]) end
logs_to_reopen()
click to toggle source
# File lib/thin/preforker/controller.rb, line 139 def logs_to_reopen require 'fcntl' logs = [] logs end
reopen_logs(logs)
click to toggle source
# File lib/thin/preforker/controller.rb, line 148 def reopen_logs logs ObjectSpace.each_object(File) { |fp| fp.reopen(fp.path, "a") if logs.include? fp.path } end
server_options_for(number)
click to toggle source
# File lib/thin/preforker/controller.rb, line 121 def server_options_for(number) @server_options ||= {} return @server_options[number] if @server_options[number] # Sets the server options for this server @server_options[number] = @options.reject { |option, value| CLUSTER_OPTIONS.include?(option) } @server_options[number].merge!(:pid => pid_file_for(number), :log => log_file_for(number), :daemonize => nil) if socket @server_options[number].merge!(:socket => socket_for(number)) elsif swiftiply? @server_options[number].merge!(:port => first_port) else @server_options[number].merge!(:port => number) end return @server_options[number] end