class Puma::Server
def process_client(client, buffer)
returning.
indicates that it supports keep alive, wait for another request before
This method support HTTP Keep-Alive so it may, depending on if the client
Given a connection on +client+, handle the incoming requests.
def process_client(client, buffer) begin clean_thread_locals = @options[:clean_thread_locals] close_socket = true requests = 0 while true case handle_request(client, buffer) when false return when :async close_socket = false return when true return unless @queue_requests buffer.reset ThreadPool.clean_thread_locals if clean_thread_locals requests += 1 # Closing keepalive sockets after they've made a reasonable # number of requests allows Puma to service many connections # fairly, even when the number of concurrent connections exceeds # the size of the threadpool. It also allows cluster mode Pumas # to keep load evenly distributed across workers, because clients # are randomly assigned a new worker when opening a new connection. # # Previously, Puma would kick connections in this conditional back # to the reactor. However, because this causes the todo set to increase # in size, the wait_until_full mutex would never unlock, leaving # any additional connections unserviced. break if requests >= MAX_FAST_INLINE check_for_more_data = @status == :run unless client.reset(check_for_more_data) close_socket = false client.set_timeout @persistent_timeout @reactor.add client return end end end # The client disconnected while we were reading data rescue ConnectionError # Swallow them. The ensure tries to close +client+ down # SSL handshake error rescue MiniSSL::SSLError => e lowlevel_error(e, client.env) ssl_socket = client.io addr = ssl_socket.peeraddr.last cert = ssl_socket.peercert close_socket = true @events.ssl_error self, addr, cert, e # The client doesn't know HTTP well rescue HttpParserError => e lowlevel_error(e, client.env) client.write_error(400) @events.parse_error self, client.env, e # Server error rescue StandardError => e lowlevel_error(e, client.env) client.write_error(500) @events.unknown_error self, e, "Read" ensure buffer.reset begin client.close if close_socket rescue IOError, SystemCallError Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue # Already closed rescue StandardError => e @events.unknown_error self, e, "Client" end end end