class Puma::Server
Attributes
app[RW]
auto_trim_time[RW]
binder[RW]
events[R]
first_data_timeout[RW]
leak_stack_on_error[RW]
max_threads[RW]
min_threads[RW]
persistent_timeout[RW]
reaping_time[RW]
thread[R]
Public Class Methods
new(app, events=Events.stdio, options={})
click to toggle source
Create a server for the rack app app
.
events
is an object which will be called when certain error
events occur to be handled. See Puma::Events for
the list of current methods to implement.
#run returns a thread that you can join on to wait for the server to do its work.
# File lib/puma/server.rb, line 50 def initialize(app, events=Events.stdio, options={}) @app = app @events = events @check, @notify = Puma::Util.pipe @status = :stop @min_threads = 0 @max_threads = 16 @auto_trim_time = 30 @reaping_time = 1 @thread = nil @thread_pool = nil @persistent_timeout = options.fetch(:persistent_timeout, PERSISTENT_TIMEOUT) @binder = Binder.new(events) @own_binder = true @first_data_timeout = FIRST_DATA_TIMEOUT @leak_stack_on_error = true @options = options @queue_requests = options[:queue_requests].nil? ? true : options[:queue_requests] ENV['RACK_ENV'] ||= "development" @mode = :http end
Public Instance Methods
backlog()
click to toggle source
# File lib/puma/server.rb, line 127 def backlog @thread_pool and @thread_pool.backlog end
cork_socket(socket)
click to toggle source
6 == Socket::IPPROTO_TCP 3 == TCP_CORK 1/0 == turn on/off
# File lib/puma/server.rb, line 106 def cork_socket(socket) begin socket.setsockopt(6, 3, 1) if socket.kind_of? TCPSocket rescue IOError, SystemCallError end end
handle_servers()
click to toggle source
# File lib/puma/server.rb, line 308 def handle_servers begin check = @check sockets = [check] + @binder.ios pool = @thread_pool queue_requests = @queue_requests remote_addr_value = nil remote_addr_header = nil case @options[:remote_address] when :value remote_addr_value = @options[:remote_address_value] when :header remote_addr_header = @options[:remote_address_header] end while @status == :run begin ios = IO.select sockets ios.first.each do |sock| if sock == check break if handle_check else begin if io = sock.accept_nonblock client = Client.new io, @binder.env(sock) if remote_addr_value client.peerip = remote_addr_value elsif remote_addr_header client.remote_addr_header = remote_addr_header end pool << client pool.wait_until_not_full unless queue_requests end rescue SystemCallError # nothing rescue Errno::ECONNABORTED # client closed the socket even before accept io.close rescue nil end end end rescue Object => e @events.unknown_error self, e, "Listen loop" end end @events.fire :state, @status graceful_shutdown if @status == :stop || @status == :restart if queue_requests @reactor.clear! @reactor.shutdown end rescue Exception => e STDERR.puts "Exception handling servers: #{e.message} (#{e.class})" STDERR.puts e.backtrace ensure @check.close @notify.close if @status != :restart and @own_binder @binder.close end end @events.fire :state, :done end
handle_servers_lopez_mode()
click to toggle source
# File lib/puma/server.rb, line 174 def handle_servers_lopez_mode begin check = @check sockets = [check] + @binder.ios pool = @thread_pool while @status == :run begin ios = IO.select sockets ios.first.each do |sock| if sock == check break if handle_check else begin if io = sock.accept_nonblock client = Client.new io, nil pool << client end rescue SystemCallError # nothing rescue Errno::ECONNABORTED # client closed the socket even before accept io.close rescue nil end end end rescue Object => e @events.unknown_error self, e, "Listen loop" end end @events.fire :state, @status graceful_shutdown if @status == :stop || @status == :restart rescue Exception => e STDERR.puts "Exception handling servers: #{e.message} (#{e.class})" STDERR.puts e.backtrace ensure @check.close @notify.close if @status != :restart and @own_binder @binder.close end end @events.fire :state, :done end
inherit_binder(bind)
click to toggle source
# File lib/puma/server.rb, line 90 def inherit_binder(bind) @binder = bind @own_binder = false end
run(background=true)
click to toggle source
Runs the server.
If background
is true (the default) then a thread is spun up
in the background to handle requests. Otherwise requests are handled
synchronously.
# File lib/puma/server.rb, line 229 def run(background=true) BasicSocket.do_not_reverse_lookup = true @events.fire :state, :booting @status = :run if @mode == :tcp return run_lopez_mode(background) end queue_requests = @queue_requests @thread_pool = ThreadPool.new(@min_threads, @max_threads, IOBuffer) do |client, buffer| # Advertise this server into the thread Thread.current[ThreadLocalKey] = self process_now = false begin if queue_requests process_now = client.eagerly_finish else client.finish process_now = true end rescue MiniSSL::SSLError => e ssl_socket = client.io addr = ssl_socket.peeraddr.last cert = ssl_socket.peercert client.close @events.ssl_error self, addr, cert, e rescue HttpParserError => e client.write_400 client.close @events.parse_error self, client.env, e rescue ConnectionError client.close else if process_now process_client client, buffer else client.set_timeout @first_data_timeout @reactor.add client end end end @thread_pool.clean_thread_locals = @options[:clean_thread_locals] if queue_requests @reactor = Reactor.new self, @thread_pool @reactor.run_in_thread end if @reaping_time @thread_pool.auto_reap!(@reaping_time) end if @auto_trim_time @thread_pool.auto_trim!(@auto_trim_time) end @events.fire :state, :running if background @thread = Thread.new { handle_servers } return @thread else handle_servers end end
run_lopez_mode(background=true)
click to toggle source
Lopez Mode == raw tcp apps
# File lib/puma/server.rb, line 137 def run_lopez_mode(background=true) @thread_pool = ThreadPool.new(@min_threads, @max_threads, Hash) do |client, tl| io = client.to_io addr = io.peeraddr.last if addr.empty? # Set unix socket addrs to localhost addr = "127.0.0.1:0" else addr = "#{addr}:#{io.peeraddr[1]}" end env = { 'thread' => tl, REMOTE_ADDR => addr } begin @app.call env, client.to_io rescue Object => e STDERR.puts "! Detected exception at toplevel: #{e.message} (#{e.class})" STDERR.puts e.backtrace end client.close unless env['detach'] end @events.fire :state, :running if background @thread = Thread.new { handle_servers_lopez_mode } return @thread else handle_servers_lopez_mode end end
running()
click to toggle source
# File lib/puma/server.rb, line 131 def running @thread_pool and @thread_pool.spawned end
tcp_mode!()
click to toggle source
# File lib/puma/server.rb, line 95 def tcp_mode! @mode = :tcp end
uncork_socket(socket)
click to toggle source
# File lib/puma/server.rb, line 113 def uncork_socket(socket) begin socket.setsockopt(6, 3, 0) if socket.kind_of? TCPSocket rescue IOError, SystemCallError end end