class Puma::Server
def handle_servers
def handle_servers @env_set_http_version = Object.const_defined?(:Rack) && ::Rack.respond_to?(:release) && Gem::Version.new(::Rack.release) < Gem::Version.new('3.1.0') begin check = @check sockets = [check] + @binder.ios pool = @thread_pool queue_requests = @queue_requests drain = options[:drain_on_shutdown] ? 0 : nil addr_send_name, addr_value = case options[:remote_address] when :value [:peerip=, options[:remote_address_value]] when :header [:remote_addr_header=, options[:remote_address_header]] when :proxy_protocol [:expect_proxy_proto=, options[:remote_address_proxy_protocol]] else [nil, nil] end while @status == :run || (drain && shutting_down?) begin ios = IO.select sockets, nil, nil, (shutting_down? ? 0 : @idle_timeout) unless ios unless shutting_down? @idle_timeout_reached = true if @clustered @worker_write << "#{PipeRequest::PIPE_IDLE}#{Process.pid}\n" rescue nil next else @log_writer.log "- Idle timeout reached" @status = :stop end end break end if @idle_timeout_reached && @clustered @idle_timeout_reached = false @worker_write << "#{PipeRequest::PIPE_IDLE}#{Process.pid}\n" rescue nil end ios.first.each do |sock| if sock == check break if handle_check else # if ThreadPool out_of_band code is running, we don't want to add # clients until the code is finished. pool.wait_while_out_of_band_running # A well rested herd (cluster) runs faster if @cluster_accept_loop_delay.on? && (busy_threads_plus_todo = pool.busy_threads) > 0 delay = @cluster_accept_loop_delay.calculate( max_threads: @max_threads, busy_threads_plus_todo: busy_threads_plus_todo ) sleep(delay) end io = begin sock.accept_nonblock rescue IO::WaitReadable next end drain += 1 if shutting_down? client = new_client(io, sock) client.send(addr_send_name, addr_value) if addr_value pool << client end end rescue IOError, Errno::EBADF # In the case that any of the sockets are unexpectedly close. raise rescue StandardError => e @log_writer.unknown_error e, nil, "Listen loop" end end @log_writer.debug { "Drained #{drain} additional connections." } if drain @events.fire :state, @status if queue_requests @queue_requests = false @reactor.shutdown end graceful_shutdown if @status == :stop || @status == :restart rescue Exception => e @log_writer.unknown_error e, nil, "Exception handling servers" ensure # Errno::EBADF is infrequently raised [@check, @notify].each do |io| begin io.close unless io.closed? rescue Errno::EBADF end end @notify = nil @check = nil end @events.fire :state, :done end