Class: Puma::Server

### Home Classes Methods

### In Files

- lib/puma/server.rb

### Parent

Object

### Methods

- ::new
- #backlog
- #cork_socket
- #handle_servers
- #handle_servers_lopez_mode
- #inherit_binder
- #run
- #run_lopez_mode
- #running
- #tcp_mode!
- #uncork_socket

### Included Modules

- Puma::Const

### Files

- Manifest.txt

### Class/Module Index

Quicksearch

- Puma
- Puma::App
- Puma::App::Status
- Puma::Binder
- Puma::CLI
- Puma::Client
- Puma::Cluster
- Puma::Cluster::Worker
- Puma::CommonLogger
- Puma::ConfigDefault
- Puma::Configuration
- Puma::Configuration::ConfigMiddleware
- Puma::ConnectionError
- Puma::Const
- Puma::ControlCLI
- Puma::DSL
- Puma::Delegation
- Puma::Events
- Puma::Events::DefaultFormatter
- Puma::Events::PidFormatter
- Puma::IOBuffer
- Puma::JRubyRestart
- Puma::JavaIOBuffer
- Puma::MiniSSL
- Puma::MiniSSL::Context
- Puma::MiniSSL::SSLError
- Puma::MiniSSL::Server
- Puma::MiniSSL::Socket
- Puma::NullIO
- Puma::Rack
- Puma::Rack::Builder
- Puma::Rack::Options
- Puma::Rack::URLMap
- Puma::Reactor
- Puma::Runner
- Puma::Server
- Puma::Single
- Puma::TCPLogger
- Puma::ThreadPool
- Puma::ThreadPool::AutoTrim
- Puma::ThreadPool::Reaper
- Puma::UnsupportedOption
- Puma::Util
- Puma::Util::HeaderHash
- OpenSSL
- OpenSSL::SSL
- OpenSSL::SSL::SSLServer
- Rack
- Rack::Handler
- Rack::Handler::Puma
- IO
- IO::WaitReadable
- Object
- Process
- String

No matching classes.

# Puma::Server

The HTTP Server itself. Serves out a single Rack app.

### 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.

Server#run returns a thread that you can join on to wait for the server to do it's 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 = 1
      @reaping_time = 1

      @thread = nil
      @thread_pool = nil

      @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 126
    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 105
    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 303
    def handle_servers
      begin
        check = @check
        sockets = [check] + @binder.ios
        pool = @thread_pool
        queue_requests = @queue_requests

        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)
                    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! if @status == :restart
          @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 173
    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 89
    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 228
    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|
        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 136
    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 130
    def running
      @thread_pool and @thread_pool.spawned
    end

tcp_mode!() click to toggle source

    # File lib/puma/server.rb, line 94
    def tcp_mode!
      @mode = :tcp
    end

uncork_socket(socket) click to toggle source

    # File lib/puma/server.rb, line 112
    def uncork_socket(socket)
      begin
        socket.setsockopt(6, 3, 0) if socket.kind_of? TCPSocket
      rescue IOError, SystemCallError
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.