run_internal

in lib/puma/reactor.rb [129:293]


    def run_internal
      monitors = @monitors
      selector = @selector

      while true
        begin
          ready = selector.select @sleep_for
        rescue IOError => e
          Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
          if monitors.any? { |mon| mon.value.closed? }
            STDERR.puts "Error in select: #{e.message} (#{e.class})"
            STDERR.puts e.backtrace

            monitors.reject! do |mon|
              if mon.value.closed?
                selector.deregister mon.value
                true
              end
            end

            retry
          else
            raise
          end
        end

        if ready
          ready.each do |mon|
            if mon.value == @ready
              @mutex.synchronize do
                case @ready.read(1)
                when "*"
                  @input.each do |c|
                    mon = nil
                    begin
                      begin
                        mon = selector.register(c, :r)
                      rescue ArgumentError
                        
                        
                        monitors.delete_if { |submon| submon.value.to_io == c.to_io }
                        selector.deregister(c)
                        mon = selector.register(c, :r)
                      end
                    rescue IOError
                      
                      
                    else
                      mon.value = c
                      @timeouts << mon if c.timeout_at
                      monitors << mon
                    end
                  end
                  @input.clear

                  @timeouts.sort! { |a,b| a.value.timeout_at <=> b.value.timeout_at }
                  calculate_sleep
                when "c"
                  monitors.reject! do |submon|
                    if submon.value == @ready
                      false
                    else
                      submon.value.close
                      begin
                        selector.deregister submon.value
                      rescue IOError
                        
                        
                      end
                      true
                    end
                  end
                when "!"
                  return
                end
              end
            else
              c = mon.value

              
              
              
              if c.timeout_at
                @mutex.synchronize do
                  @timeouts.delete mon
                end
              end

              begin
                if c.try_to_finish
                  @app_pool << c
                  clear_monitor mon
                end

              
              
              
              rescue ConnectionError
                c.write_error(500)
                c.close

                clear_monitor mon

              
              rescue MiniSSL::SSLError => e
                @server.lowlevel_error(e, c.env)

                ssl_socket = c.io
                begin
                  addr = ssl_socket.peeraddr.last
                
                rescue IOError, Errno::EINVAL
                  addr = "<unknown>"
                end

                cert = ssl_socket.peercert

                c.close
                clear_monitor mon

                @events.ssl_error @server, addr, cert, e

              
              rescue HttpParserError => e
                @server.lowlevel_error(e, c.env)

                c.write_error(400)
                c.close

                clear_monitor mon

                @events.parse_error @server, c.env, e
              rescue StandardError => e
                @server.lowlevel_error(e, c.env)

                c.write_error(500)
                c.close

                clear_monitor mon
              end
            end
          end
        end

        unless @timeouts.empty?
          @mutex.synchronize do
            now = Time.now

            while @timeouts.first.value.timeout_at < now
              mon = @timeouts.shift
              c = mon.value
              c.write_error(408) if c.in_data_phase
              c.close

              clear_monitor mon

              break if @timeouts.empty?
            end

            calculate_sleep
          end
        end
      end
    end