puma 5.6.4-java → 6.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +136 -3
- data/README.md +21 -17
- data/bin/puma-wild +1 -1
- data/docs/compile_options.md +34 -0
- data/docs/fork_worker.md +1 -3
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/extconf.rb +18 -10
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +63 -24
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +166 -65
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +6 -3
- data/lib/puma/binder.rb +37 -43
- data/lib/puma/cli.rb +11 -17
- data/lib/puma/client.rb +22 -12
- data/lib/puma/cluster/worker.rb +13 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +28 -25
- data/lib/puma/configuration.rb +74 -58
- data/lib/puma/const.rb +14 -18
- data/lib/puma/control_cli.rb +21 -18
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +94 -49
- data/lib/puma/error_logger.rb +17 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +29 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +107 -156
- data/lib/puma/log_writer.rb +137 -0
- data/lib/puma/minissl/context_builder.rb +23 -12
- data/lib/puma/minissl.rb +91 -15
- data/lib/puma/null_io.rb +5 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/rack/builder.rb +4 -4
- data/lib/puma/rack_default.rb +1 -1
- data/lib/puma/reactor.rb +3 -3
- data/lib/puma/request.rb +291 -156
- data/lib/puma/runner.rb +41 -20
- data/lib/puma/server.rb +53 -64
- data/lib/puma/single.rb +10 -10
- data/lib/puma/state_file.rb +2 -4
- data/lib/puma/systemd.rb +3 -2
- data/lib/puma/thread_pool.rb +16 -13
- data/lib/puma/util.rb +12 -14
- data/lib/puma.rb +11 -8
- data/lib/rack/handler/puma.rb +9 -9
- metadata +7 -3
- data/lib/puma/queue_close.rb +0 -26
    
        data/lib/puma/runner.rb
    CHANGED
    
    | @@ -1,23 +1,29 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 3 | 
            +
            require_relative 'server'
         | 
| 4 | 
            +
            require_relative 'const'
         | 
| 5 5 |  | 
| 6 6 | 
             
            module Puma
         | 
| 7 7 | 
             
              # Generic class that is used by `Puma::Cluster` and `Puma::Single` to
         | 
| 8 8 | 
             
              # serve requests. This class spawns a new instance of `Puma::Server` via
         | 
| 9 9 | 
             
              # a call to `start_server`.
         | 
| 10 10 | 
             
              class Runner
         | 
| 11 | 
            -
                def initialize( | 
| 12 | 
            -
                  @launcher =  | 
| 13 | 
            -
                  @ | 
| 14 | 
            -
                  @ | 
| 11 | 
            +
                def initialize(launcher)
         | 
| 12 | 
            +
                  @launcher = launcher
         | 
| 13 | 
            +
                  @log_writer = launcher.log_writer
         | 
| 14 | 
            +
                  @events = launcher.events
         | 
| 15 | 
            +
                  @config = launcher.config
         | 
| 16 | 
            +
                  @options = launcher.options
         | 
| 15 17 | 
             
                  @app = nil
         | 
| 16 18 | 
             
                  @control = nil
         | 
| 17 19 | 
             
                  @started_at = Time.now
         | 
| 18 20 | 
             
                  @wakeup = nil
         | 
| 19 21 | 
             
                end
         | 
| 20 22 |  | 
| 23 | 
            +
                # Returns the hash of configuration options.
         | 
| 24 | 
            +
                # @return [Puma::UserFileDefaultOptions]
         | 
| 25 | 
            +
                attr_reader :options
         | 
| 26 | 
            +
             | 
| 21 27 | 
             
                def wakeup!
         | 
| 22 28 | 
             
                  return unless @wakeup
         | 
| 23 29 |  | 
| @@ -36,27 +42,27 @@ module Puma | |
| 36 42 | 
             
                end
         | 
| 37 43 |  | 
| 38 44 | 
             
                def log(str)
         | 
| 39 | 
            -
                  @ | 
| 45 | 
            +
                  @log_writer.log str
         | 
| 40 46 | 
             
                end
         | 
| 41 47 |  | 
| 42 48 | 
             
                # @version 5.0.0
         | 
| 43 49 | 
             
                def stop_control
         | 
| 44 | 
            -
                  @control | 
| 50 | 
            +
                  @control&.stop true
         | 
| 45 51 | 
             
                end
         | 
| 46 52 |  | 
| 47 53 | 
             
                def error(str)
         | 
| 48 | 
            -
                  @ | 
| 54 | 
            +
                  @log_writer.error str
         | 
| 49 55 | 
             
                end
         | 
| 50 56 |  | 
| 51 57 | 
             
                def debug(str)
         | 
| 52 | 
            -
                  @ | 
| 58 | 
            +
                  @log_writer.log "- #{str}" if @options[:debug]
         | 
| 53 59 | 
             
                end
         | 
| 54 60 |  | 
| 55 61 | 
             
                def start_control
         | 
| 56 62 | 
             
                  str = @options[:control_url]
         | 
| 57 63 | 
             
                  return unless str
         | 
| 58 64 |  | 
| 59 | 
            -
                   | 
| 65 | 
            +
                  require_relative 'app/status'
         | 
| 60 66 |  | 
| 61 67 | 
             
                  if token = @options[:control_auth_token]
         | 
| 62 68 | 
             
                    token = nil if token.empty? || token == 'none'
         | 
| @@ -64,10 +70,12 @@ module Puma | |
| 64 70 |  | 
| 65 71 | 
             
                  app = Puma::App::Status.new @launcher, token
         | 
| 66 72 |  | 
| 67 | 
            -
                   | 
| 68 | 
            -
             | 
| 73 | 
            +
                  # A Reactor is not created aand nio4r is not loaded when 'queue_requests: false'
         | 
| 74 | 
            +
                  # Use `nil` for events, no hooks in control server
         | 
| 75 | 
            +
                  control = Puma::Server.new app, nil,
         | 
| 76 | 
            +
                    { min_threads: 0, max_threads: 1, queue_requests: false, log_writer: @log_writer }
         | 
| 69 77 |  | 
| 70 | 
            -
                  control.binder.parse [str],  | 
| 78 | 
            +
                  control.binder.parse [str], nil, 'Starting control server'
         | 
| 71 79 |  | 
| 72 80 | 
             
                  control.run thread_name: 'ctl'
         | 
| 73 81 | 
             
                  @control = control
         | 
| @@ -141,29 +149,29 @@ module Puma | |
| 141 149 | 
             
                end
         | 
| 142 150 |  | 
| 143 151 | 
             
                def load_and_bind
         | 
| 144 | 
            -
                  unless @ | 
| 152 | 
            +
                  unless @config.app_configured?
         | 
| 145 153 | 
             
                    error "No application configured, nothing to run"
         | 
| 146 154 | 
             
                    exit 1
         | 
| 147 155 | 
             
                  end
         | 
| 148 156 |  | 
| 149 157 | 
             
                  begin
         | 
| 150 | 
            -
                    @app = @ | 
| 158 | 
            +
                    @app = @config.app
         | 
| 151 159 | 
             
                  rescue Exception => e
         | 
| 152 160 | 
             
                    log "! Unable to load application: #{e.class}: #{e.message}"
         | 
| 153 161 | 
             
                    raise e
         | 
| 154 162 | 
             
                  end
         | 
| 155 163 |  | 
| 156 | 
            -
                  @launcher.binder.parse @options[:binds] | 
| 164 | 
            +
                  @launcher.binder.parse @options[:binds]
         | 
| 157 165 | 
             
                end
         | 
| 158 166 |  | 
| 159 167 | 
             
                # @!attribute [r] app
         | 
| 160 168 | 
             
                def app
         | 
| 161 | 
            -
                  @app ||= @ | 
| 169 | 
            +
                  @app ||= @config.app
         | 
| 162 170 | 
             
                end
         | 
| 163 171 |  | 
| 164 172 | 
             
                def start_server
         | 
| 165 | 
            -
                  server = Puma::Server.new | 
| 166 | 
            -
                  server.inherit_binder | 
| 173 | 
            +
                  server = Puma::Server.new(app, @events, @options)
         | 
| 174 | 
            +
                  server.inherit_binder(@launcher.binder)
         | 
| 167 175 | 
             
                  server
         | 
| 168 176 | 
             
                end
         | 
| 169 177 |  | 
| @@ -173,5 +181,18 @@ module Puma | |
| 173 181 | 
             
                    raise "Cannot redirect #{io_name} to #{path}"
         | 
| 174 182 | 
             
                  end
         | 
| 175 183 | 
             
                end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                def stats
         | 
| 186 | 
            +
                  {
         | 
| 187 | 
            +
                    versions: {
         | 
| 188 | 
            +
                      puma: Puma::Const::PUMA_VERSION,
         | 
| 189 | 
            +
                      ruby: {
         | 
| 190 | 
            +
                        engine: RUBY_ENGINE,
         | 
| 191 | 
            +
                        version: RUBY_VERSION,
         | 
| 192 | 
            +
                        patchlevel: RUBY_PATCHLEVEL
         | 
| 193 | 
            +
                      }
         | 
| 194 | 
            +
                    }
         | 
| 195 | 
            +
                  }
         | 
| 196 | 
            +
                end
         | 
| 176 197 | 
             
              end
         | 
| 177 198 | 
             
            end
         | 
    
        data/lib/puma/server.rb
    CHANGED
    
    | @@ -2,19 +2,20 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'stringio'
         | 
| 4 4 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 5 | 
            +
            require_relative 'thread_pool'
         | 
| 6 | 
            +
            require_relative 'const'
         | 
| 7 | 
            +
            require_relative 'log_writer'
         | 
| 8 | 
            +
            require_relative 'events'
         | 
| 9 | 
            +
            require_relative 'null_io'
         | 
| 10 | 
            +
            require_relative 'reactor'
         | 
| 11 | 
            +
            require_relative 'client'
         | 
| 12 | 
            +
            require_relative 'binder'
         | 
| 13 | 
            +
            require_relative 'util'
         | 
| 14 | 
            +
            require_relative 'io_buffer'
         | 
| 15 | 
            +
            require_relative 'request'
         | 
| 15 16 |  | 
| 16 17 | 
             
            require 'socket'
         | 
| 17 | 
            -
            require 'io/wait'
         | 
| 18 | 
            +
            require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
         | 
| 18 19 | 
             
            require 'forwardable'
         | 
| 19 20 |  | 
| 20 21 | 
             
            module Puma
         | 
| @@ -30,12 +31,12 @@ module Puma | |
| 30 31 | 
             
              #
         | 
| 31 32 | 
             
              # Each `Puma::Server` will have one reactor and one thread pool.
         | 
| 32 33 | 
             
              class Server
         | 
| 33 | 
            -
             | 
| 34 34 | 
             
                include Puma::Const
         | 
| 35 35 | 
             
                include Request
         | 
| 36 36 | 
             
                extend Forwardable
         | 
| 37 37 |  | 
| 38 38 | 
             
                attr_reader :thread
         | 
| 39 | 
            +
                attr_reader :log_writer
         | 
| 39 40 | 
             
                attr_reader :events
         | 
| 40 41 | 
             
                attr_reader :min_threads, :max_threads  # for #stats
         | 
| 41 42 | 
             
                attr_reader :requests_count             # @version 5.0.0
         | 
| @@ -45,11 +46,6 @@ module Puma | |
| 45 46 | 
             
                  :leak_stack_on_error,
         | 
| 46 47 | 
             
                  :persistent_timeout, :reaping_time
         | 
| 47 48 |  | 
| 48 | 
            -
                # @deprecated v6.0.0
         | 
| 49 | 
            -
                attr_writer :auto_trim_time, :early_hints, :first_data_timeout,
         | 
| 50 | 
            -
                  :leak_stack_on_error, :min_threads, :max_threads,
         | 
| 51 | 
            -
                  :persistent_timeout, :reaping_time
         | 
| 52 | 
            -
             | 
| 53 49 | 
             
                attr_accessor :app
         | 
| 54 50 | 
             
                attr_accessor :binder
         | 
| 55 51 |  | 
| @@ -60,8 +56,9 @@ module Puma | |
| 60 56 |  | 
| 61 57 | 
             
                # Create a server for the rack app +app+.
         | 
| 62 58 | 
             
                #
         | 
| 63 | 
            -
                # + | 
| 64 | 
            -
                # | 
| 59 | 
            +
                # +log_writer+ is a Puma::LogWriter object used to log info and error messages.
         | 
| 60 | 
            +
                #
         | 
| 61 | 
            +
                # +events+ is a Puma::Events object used to notify application status events.
         | 
| 65 62 | 
             
                #
         | 
| 66 63 | 
             
                # Server#run returns a thread that you can join on to wait for the server
         | 
| 67 64 | 
             
                # to do its work.
         | 
| @@ -70,34 +67,40 @@ module Puma | |
| 70 67 | 
             
                #   and have default values set via +fetch+.  Normally the values are set via
         | 
| 71 68 | 
             
                #   `::Puma::Configuration.puma_default_options`.
         | 
| 72 69 | 
             
                #
         | 
| 73 | 
            -
                 | 
| 70 | 
            +
                # @note The `events` parameter is set to nil, and set to `Events.new` in code.
         | 
| 71 | 
            +
                #   Often `options` needs to be passed, but `events` does not.  Using nil allows
         | 
| 72 | 
            +
                #   calling code to not require events.rb.
         | 
| 73 | 
            +
                #
         | 
| 74 | 
            +
                def initialize(app, events = nil, options = {})
         | 
| 74 75 | 
             
                  @app = app
         | 
| 75 | 
            -
                  @events = events
         | 
| 76 | 
            +
                  @events = events || Events.new
         | 
| 76 77 |  | 
| 77 78 | 
             
                  @check, @notify = nil
         | 
| 78 79 | 
             
                  @status = :stop
         | 
| 79 80 |  | 
| 80 | 
            -
                  @auto_trim_time = 30
         | 
| 81 | 
            -
                  @reaping_time = 1
         | 
| 82 | 
            -
             | 
| 83 81 | 
             
                  @thread = nil
         | 
| 84 82 | 
             
                  @thread_pool = nil
         | 
| 85 83 |  | 
| 86 | 
            -
                  @options = options
         | 
| 84 | 
            +
                  @options = if options.is_a?(UserFileDefaultOptions)
         | 
| 85 | 
            +
                    options
         | 
| 86 | 
            +
                  else
         | 
| 87 | 
            +
                    UserFileDefaultOptions.new(options, Configuration::DEFAULTS)
         | 
| 88 | 
            +
                  end
         | 
| 87 89 |  | 
| 88 | 
            -
                  @ | 
| 89 | 
            -
                  @ | 
| 90 | 
            -
                  @ | 
| 91 | 
            -
                  @ | 
| 92 | 
            -
                  @ | 
| 93 | 
            -
                  @ | 
| 94 | 
            -
                  @ | 
| 95 | 
            -
                  @ | 
| 90 | 
            +
                  @log_writer          = @options.fetch :log_writer, LogWriter.stdio
         | 
| 91 | 
            +
                  @early_hints         = @options[:early_hints]
         | 
| 92 | 
            +
                  @first_data_timeout  = @options[:first_data_timeout]
         | 
| 93 | 
            +
                  @min_threads         = @options[:min_threads]
         | 
| 94 | 
            +
                  @max_threads         = @options[:max_threads]
         | 
| 95 | 
            +
                  @persistent_timeout  = @options[:persistent_timeout]
         | 
| 96 | 
            +
                  @queue_requests      = @options[:queue_requests]
         | 
| 97 | 
            +
                  @max_fast_inline     = @options[:max_fast_inline]
         | 
| 98 | 
            +
                  @io_selector_backend = @options[:io_selector_backend]
         | 
| 96 99 |  | 
| 97 100 | 
             
                  temp = !!(@options[:environment] =~ /\A(development|test)\z/)
         | 
| 98 101 | 
             
                  @leak_stack_on_error = @options[:environment] ? temp : true
         | 
| 99 102 |  | 
| 100 | 
            -
                  @binder = Binder.new( | 
| 103 | 
            +
                  @binder = Binder.new(log_writer)
         | 
| 101 104 |  | 
| 102 105 | 
             
                  ENV['RACK_ENV'] ||= "development"
         | 
| 103 106 |  | 
| @@ -193,12 +196,12 @@ module Puma | |
| 193 196 |  | 
| 194 197 | 
             
                # @!attribute [r] backlog
         | 
| 195 198 | 
             
                def backlog
         | 
| 196 | 
            -
                  @thread_pool | 
| 199 | 
            +
                  @thread_pool&.backlog
         | 
| 197 200 | 
             
                end
         | 
| 198 201 |  | 
| 199 202 | 
             
                # @!attribute [r] running
         | 
| 200 203 | 
             
                def running
         | 
| 201 | 
            -
                  @thread_pool | 
| 204 | 
            +
                  @thread_pool&.spawned
         | 
| 202 205 | 
             
                end
         | 
| 203 206 |  | 
| 204 207 |  | 
| @@ -211,7 +214,7 @@ module Puma | |
| 211 214 | 
             
                # value would be 4 until it finishes processing.
         | 
| 212 215 | 
             
                # @!attribute [r] pool_capacity
         | 
| 213 216 | 
             
                def pool_capacity
         | 
| 214 | 
            -
                  @thread_pool | 
| 217 | 
            +
                  @thread_pool&.pool_capacity
         | 
| 215 218 | 
             
                end
         | 
| 216 219 |  | 
| 217 220 | 
             
                # Runs the server.
         | 
| @@ -227,29 +230,16 @@ module Puma | |
| 227 230 |  | 
| 228 231 | 
             
                  @status = :run
         | 
| 229 232 |  | 
| 230 | 
            -
                  @thread_pool = ThreadPool.new(
         | 
| 231 | 
            -
                    thread_name,
         | 
| 232 | 
            -
                    @min_threads,
         | 
| 233 | 
            -
                    @max_threads,
         | 
| 234 | 
            -
                    ::Puma::IOBuffer,
         | 
| 235 | 
            -
                    &method(:process_client)
         | 
| 236 | 
            -
                  )
         | 
| 237 | 
            -
             | 
| 238 | 
            -
                  @thread_pool.out_of_band_hook = @options[:out_of_band]
         | 
| 239 | 
            -
                  @thread_pool.clean_thread_locals = @options[:clean_thread_locals]
         | 
| 233 | 
            +
                  @thread_pool = ThreadPool.new(thread_name, @options) { |a, b| process_client a, b }
         | 
| 240 234 |  | 
| 241 235 | 
             
                  if @queue_requests
         | 
| 242 | 
            -
                    @reactor = Reactor.new(@io_selector_backend | 
| 236 | 
            +
                    @reactor = Reactor.new(@io_selector_backend) { |c| reactor_wakeup c }
         | 
| 243 237 | 
             
                    @reactor.run
         | 
| 244 238 | 
             
                  end
         | 
| 245 239 |  | 
| 246 | 
            -
                  if @reaping_time
         | 
| 247 | 
            -
                    @thread_pool.auto_reap!(@reaping_time)
         | 
| 248 | 
            -
                  end
         | 
| 249 240 |  | 
| 250 | 
            -
                  if @ | 
| 251 | 
            -
             | 
| 252 | 
            -
                  end
         | 
| 241 | 
            +
                  @thread_pool.auto_reap! if @options[:reaping_time]
         | 
| 242 | 
            +
                  @thread_pool.auto_trim! if @options[:auto_trim_time]
         | 
| 253 243 |  | 
| 254 244 | 
             
                  @check, @notify = Puma::Util.pipe unless @notify
         | 
| 255 245 |  | 
| @@ -353,11 +343,11 @@ module Puma | |
| 353 343 | 
             
                        # In the case that any of the sockets are unexpectedly close.
         | 
| 354 344 | 
             
                        raise
         | 
| 355 345 | 
             
                      rescue StandardError => e
         | 
| 356 | 
            -
                        @ | 
| 346 | 
            +
                        @log_writer.unknown_error e, nil, "Listen loop"
         | 
| 357 347 | 
             
                      end
         | 
| 358 348 | 
             
                    end
         | 
| 359 349 |  | 
| 360 | 
            -
                    @ | 
| 350 | 
            +
                    @log_writer.debug "Drained #{drain} additional connections." if drain
         | 
| 361 351 | 
             
                    @events.fire :state, @status
         | 
| 362 352 |  | 
| 363 353 | 
             
                    if queue_requests
         | 
| @@ -366,14 +356,13 @@ module Puma | |
| 366 356 | 
             
                    end
         | 
| 367 357 | 
             
                    graceful_shutdown if @status == :stop || @status == :restart
         | 
| 368 358 | 
             
                  rescue Exception => e
         | 
| 369 | 
            -
                    @ | 
| 359 | 
            +
                    @log_writer.unknown_error e, nil, "Exception handling servers"
         | 
| 370 360 | 
             
                  ensure
         | 
| 371 | 
            -
                    # RuntimeError is Ruby 2.2 issue, can't modify frozen IOError
         | 
| 372 361 | 
             
                    # Errno::EBADF is infrequently raised
         | 
| 373 362 | 
             
                    [@check, @notify].each do |io|
         | 
| 374 363 | 
             
                      begin
         | 
| 375 364 | 
             
                        io.close unless io.closed?
         | 
| 376 | 
            -
                      rescue Errno::EBADF | 
| 365 | 
            +
                      rescue Errno::EBADF
         | 
| 377 366 | 
             
                      end
         | 
| 378 367 | 
             
                    end
         | 
| 379 368 | 
             
                    @notify = nil
         | 
| @@ -488,7 +477,7 @@ module Puma | |
| 488 477 | 
             
                      Puma::Util.purge_interrupt_queue
         | 
| 489 478 | 
             
                      # Already closed
         | 
| 490 479 | 
             
                    rescue StandardError => e
         | 
| 491 | 
            -
                      @ | 
| 480 | 
            +
                      @log_writer.unknown_error e, nil, "Client"
         | 
| 492 481 | 
             
                    end
         | 
| 493 482 | 
             
                  end
         | 
| 494 483 | 
             
                end
         | 
| @@ -511,16 +500,16 @@ module Puma | |
| 511 500 | 
             
                  lowlevel_error(e, client.env)
         | 
| 512 501 | 
             
                  case e
         | 
| 513 502 | 
             
                  when MiniSSL::SSLError
         | 
| 514 | 
            -
                    @ | 
| 503 | 
            +
                    @log_writer.ssl_error e, client.io
         | 
| 515 504 | 
             
                  when HttpParserError
         | 
| 516 505 | 
             
                    client.write_error(400)
         | 
| 517 | 
            -
                    @ | 
| 506 | 
            +
                    @log_writer.parse_error e, client
         | 
| 518 507 | 
             
                  when HttpParserError501
         | 
| 519 508 | 
             
                    client.write_error(501)
         | 
| 520 | 
            -
                    @ | 
| 509 | 
            +
                    @log_writer.parse_error e, client
         | 
| 521 510 | 
             
                  else
         | 
| 522 511 | 
             
                    client.write_error(500)
         | 
| 523 | 
            -
                    @ | 
| 512 | 
            +
                    @log_writer.unknown_error e, nil, "Read"
         | 
| 524 513 | 
             
                  end
         | 
| 525 514 | 
             
                end
         | 
| 526 515 |  | 
    
        data/lib/puma/single.rb
    CHANGED
    
    | @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 3 | 
            +
            require_relative 'runner'
         | 
| 4 | 
            +
            require_relative 'detect'
         | 
| 5 | 
            +
            require_relative 'plugin'
         | 
| 6 6 |  | 
| 7 7 | 
             
            module Puma
         | 
| 8 8 | 
             
              # This class is instantiated by the `Puma::Launcher` and used
         | 
| @@ -17,25 +17,25 @@ module Puma | |
| 17 17 | 
             
                def stats
         | 
| 18 18 | 
             
                  {
         | 
| 19 19 | 
             
                    started_at: @started_at.utc.iso8601
         | 
| 20 | 
            -
                  }.merge(@server.stats)
         | 
| 20 | 
            +
                  }.merge(@server.stats).merge(super)
         | 
| 21 21 | 
             
                end
         | 
| 22 22 |  | 
| 23 23 | 
             
                def restart
         | 
| 24 | 
            -
                  @server | 
| 24 | 
            +
                  @server&.begin_restart
         | 
| 25 25 | 
             
                end
         | 
| 26 26 |  | 
| 27 27 | 
             
                def stop
         | 
| 28 | 
            -
                  @server | 
| 28 | 
            +
                  @server&.stop false
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| 31 31 | 
             
                def halt
         | 
| 32 | 
            -
                  @server | 
| 32 | 
            +
                  @server&.halt
         | 
| 33 33 | 
             
                end
         | 
| 34 34 |  | 
| 35 35 | 
             
                def stop_blocked
         | 
| 36 36 | 
             
                  log "- Gracefully stopping, waiting for requests to finish"
         | 
| 37 | 
            -
                  @control | 
| 38 | 
            -
                  @server | 
| 37 | 
            +
                  @control&.stop true
         | 
| 38 | 
            +
                  @server&.stop true
         | 
| 39 39 | 
             
                end
         | 
| 40 40 |  | 
| 41 41 | 
             
                def run
         | 
| @@ -55,7 +55,7 @@ module Puma | |
| 55 55 | 
             
                  log "Use Ctrl-C to stop"
         | 
| 56 56 | 
             
                  redirect_io
         | 
| 57 57 |  | 
| 58 | 
            -
                  @ | 
| 58 | 
            +
                  @events.fire_on_booted!
         | 
| 59 59 |  | 
| 60 60 | 
             
                  begin
         | 
| 61 61 | 
             
                    server_thread.join
         | 
    
        data/lib/puma/state_file.rb
    CHANGED
    
    | @@ -15,15 +15,12 @@ module Puma | |
| 15 15 |  | 
| 16 16 | 
             
                ALLOWED_FIELDS = %w!control_url control_auth_token pid running_from!
         | 
| 17 17 |  | 
| 18 | 
            -
                # @deprecated 6.0.0
         | 
| 19 | 
            -
                FIELDS = ALLOWED_FIELDS
         | 
| 20 | 
            -
             | 
| 21 18 | 
             
                def initialize
         | 
| 22 19 | 
             
                  @options = {}
         | 
| 23 20 | 
             
                end
         | 
| 24 21 |  | 
| 25 22 | 
             
                def save(path, permission = nil)
         | 
| 26 | 
            -
                  contents = "---\n" | 
| 23 | 
            +
                  contents = +"---\n"
         | 
| 27 24 | 
             
                  @options.each do |k,v|
         | 
| 28 25 | 
             
                    next unless ALLOWED_FIELDS.include? k
         | 
| 29 26 | 
             
                    case v
         | 
| @@ -50,6 +47,7 @@ module Puma | |
| 50 47 | 
             
                    v = v.strip
         | 
| 51 48 | 
             
                    @options[k] =
         | 
| 52 49 | 
             
                      case v
         | 
| 50 | 
            +
                      when ''              then nil
         | 
| 53 51 | 
             
                      when /\A\d+\z/       then v.to_i
         | 
| 54 52 | 
             
                      when /\A\d+\.\d+\z/  then v.to_f
         | 
| 55 53 | 
             
                      else                      v.gsub(/\A"|"\z/, '')
         | 
    
        data/lib/puma/systemd.rb
    CHANGED
    
    | @@ -4,7 +4,8 @@ require 'sd_notify' | |
| 4 4 |  | 
| 5 5 | 
             
            module Puma
         | 
| 6 6 | 
             
              class Systemd
         | 
| 7 | 
            -
                def initialize(events)
         | 
| 7 | 
            +
                def initialize(log_writer, events)
         | 
| 8 | 
            +
                  @log_writer = log_writer
         | 
| 8 9 | 
             
                  @events = events
         | 
| 9 10 | 
             
                end
         | 
| 10 11 |  | 
| @@ -40,7 +41,7 @@ module Puma | |
| 40 41 | 
             
                end
         | 
| 41 42 |  | 
| 42 43 | 
             
                def log(str)
         | 
| 43 | 
            -
                  @ | 
| 44 | 
            +
                  @log_writer.log(str)
         | 
| 44 45 | 
             
                end
         | 
| 45 46 | 
             
              end
         | 
| 46 47 | 
             
            end
         | 
    
        data/lib/puma/thread_pool.rb
    CHANGED
    
    | @@ -2,6 +2,8 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'thread'
         | 
| 4 4 |  | 
| 5 | 
            +
            require_relative 'io_buffer'
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
            module Puma
         | 
| 6 8 | 
             
              # Internal Docs for A simple thread pool management object.
         | 
| 7 9 | 
             
              #
         | 
| @@ -29,7 +31,7 @@ module Puma | |
| 29 31 | 
             
                # The block passed is the work that will be performed in each
         | 
| 30 32 | 
             
                # thread.
         | 
| 31 33 | 
             
                #
         | 
| 32 | 
            -
                def initialize(name,  | 
| 34 | 
            +
                def initialize(name, options = {}, &block)
         | 
| 33 35 | 
             
                  @not_empty = ConditionVariable.new
         | 
| 34 36 | 
             
                  @not_full = ConditionVariable.new
         | 
| 35 37 | 
             
                  @mutex = Mutex.new
         | 
| @@ -40,10 +42,14 @@ module Puma | |
| 40 42 | 
             
                  @waiting = 0
         | 
| 41 43 |  | 
| 42 44 | 
             
                  @name = name
         | 
| 43 | 
            -
                  @min = Integer( | 
| 44 | 
            -
                  @max = Integer( | 
| 45 | 
            +
                  @min = Integer(options[:min_threads])
         | 
| 46 | 
            +
                  @max = Integer(options[:max_threads])
         | 
| 45 47 | 
             
                  @block = block
         | 
| 46 | 
            -
                  @extra =  | 
| 48 | 
            +
                  @extra = [::Puma::IOBuffer]
         | 
| 49 | 
            +
                  @out_of_band = options[:out_of_band]
         | 
| 50 | 
            +
                  @clean_thread_locals = options[:clean_thread_locals]
         | 
| 51 | 
            +
                  @reaping_time = options[:reaping_time]
         | 
| 52 | 
            +
                  @auto_trim_time = options[:auto_trim_time]
         | 
| 47 53 |  | 
| 48 54 | 
             
                  @shutdown = false
         | 
| 49 55 |  | 
| @@ -62,14 +68,11 @@ module Puma | |
| 62 68 | 
             
                    end
         | 
| 63 69 | 
             
                  end
         | 
| 64 70 |  | 
| 65 | 
            -
                  @clean_thread_locals = false
         | 
| 66 71 | 
             
                  @force_shutdown = false
         | 
| 67 72 | 
             
                  @shutdown_mutex = Mutex.new
         | 
| 68 73 | 
             
                end
         | 
| 69 74 |  | 
| 70 75 | 
             
                attr_reader :spawned, :trim_requested, :waiting
         | 
| 71 | 
            -
                attr_accessor :clean_thread_locals
         | 
| 72 | 
            -
                attr_accessor :out_of_band_hook # @version 5.0.0
         | 
| 73 76 |  | 
| 74 77 | 
             
                def self.clean_thread_locals
         | 
| 75 78 | 
             
                  Thread.current.keys.each do |key| # rubocop: disable Style/HashEachMethods
         | 
| @@ -160,12 +163,12 @@ module Puma | |
| 160 163 |  | 
| 161 164 | 
             
                # @version 5.0.0
         | 
| 162 165 | 
             
                def trigger_out_of_band_hook
         | 
| 163 | 
            -
                  return false unless  | 
| 166 | 
            +
                  return false unless @out_of_band&.any?
         | 
| 164 167 |  | 
| 165 168 | 
             
                  # we execute on idle hook when all threads are free
         | 
| 166 169 | 
             
                  return false unless @spawned == @waiting
         | 
| 167 170 |  | 
| 168 | 
            -
                   | 
| 171 | 
            +
                  @out_of_band.each(&:call)
         | 
| 169 172 | 
             
                  true
         | 
| 170 173 | 
             
                rescue Exception => e
         | 
| 171 174 | 
             
                  STDERR.puts "Exception calling out_of_band_hook: #{e.message} (#{e.class})"
         | 
| @@ -319,12 +322,12 @@ module Puma | |
| 319 322 | 
             
                  end
         | 
| 320 323 | 
             
                end
         | 
| 321 324 |  | 
| 322 | 
            -
                def auto_trim!(timeout | 
| 325 | 
            +
                def auto_trim!(timeout=@auto_trim_time)
         | 
| 323 326 | 
             
                  @auto_trim = Automaton.new(self, timeout, "#{@name} threadpool trimmer", :trim)
         | 
| 324 327 | 
             
                  @auto_trim.start!
         | 
| 325 328 | 
             
                end
         | 
| 326 329 |  | 
| 327 | 
            -
                def auto_reap!(timeout | 
| 330 | 
            +
                def auto_reap!(timeout=@reaping_time)
         | 
| 328 331 | 
             
                  @reaper = Automaton.new(self, timeout, "#{@name} threadpool reaper", :reap)
         | 
| 329 332 | 
             
                  @reaper.start!
         | 
| 330 333 | 
             
                end
         | 
| @@ -354,8 +357,8 @@ module Puma | |
| 354 357 | 
             
                    @not_empty.broadcast
         | 
| 355 358 | 
             
                    @not_full.broadcast
         | 
| 356 359 |  | 
| 357 | 
            -
                    @auto_trim | 
| 358 | 
            -
                    @reaper | 
| 360 | 
            +
                    @auto_trim&.stop
         | 
| 361 | 
            +
                    @reaper&.stop
         | 
| 359 362 | 
             
                    # dup workers so that we join them all safely
         | 
| 360 363 | 
             
                    @workers.dup
         | 
| 361 364 | 
             
                  end
         | 
    
        data/lib/puma/util.rb
    CHANGED
    
    | @@ -17,29 +17,27 @@ module Puma | |
| 17 17 | 
             
                  Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 | 
            -
                #  | 
| 21 | 
            -
                #  | 
| 20 | 
            +
                # Escapes and unescapes a URI escaped string with
         | 
| 21 | 
            +
                # +encoding+. +encoding+ will be the target encoding of the string
         | 
| 22 | 
            +
                # returned, and it defaults to UTF-8
         | 
| 22 23 | 
             
                if defined?(::Encoding)
         | 
| 24 | 
            +
                  def escape(s, encoding = Encoding::UTF_8)
         | 
| 25 | 
            +
                    URI.encode_www_form_component(s, encoding)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 23 28 | 
             
                  def unescape(s, encoding = Encoding::UTF_8)
         | 
| 24 29 | 
             
                    URI.decode_www_form_component(s, encoding)
         | 
| 25 30 | 
             
                  end
         | 
| 26 31 | 
             
                else
         | 
| 27 | 
            -
                  def  | 
| 28 | 
            -
                    URI. | 
| 32 | 
            +
                  def escape(s, encoding = nil)
         | 
| 33 | 
            +
                    URI.encode_www_form_component(s, encoding)
         | 
| 29 34 | 
             
                  end
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
                module_function :unescape
         | 
| 32 35 |  | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                  events.log "! Promoting existing objects to old generation..."
         | 
| 36 | 
            -
                  4.times { GC.start(full_mark: false) }
         | 
| 37 | 
            -
                  if GC.respond_to?(:compact)
         | 
| 38 | 
            -
                    events.log "! Compacting..."
         | 
| 39 | 
            -
                    GC.compact
         | 
| 36 | 
            +
                  def unescape(s, encoding = nil)
         | 
| 37 | 
            +
                    URI.decode_www_form_component(s, encoding)
         | 
| 40 38 | 
             
                  end
         | 
| 41 | 
            -
                  events.log "! Friendly fork preparation complete."
         | 
| 42 39 | 
             
                end
         | 
| 40 | 
            +
                module_function :unescape, :escape
         | 
| 43 41 |  | 
| 44 42 | 
             
                DEFAULT_SEP = /[&;] */n
         | 
| 45 43 |  | 
    
        data/lib/puma.rb
    CHANGED
    
    | @@ -10,14 +10,19 @@ require 'stringio' | |
| 10 10 |  | 
| 11 11 | 
             
            require 'thread'
         | 
| 12 12 |  | 
| 13 | 
            +
            # use require, see https://github.com/puma/puma/pull/2381
         | 
| 13 14 | 
             
            require 'puma/puma_http11'
         | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            require_relative 'puma/detect'
         | 
| 17 | 
            +
            require_relative 'puma/json_serialization'
         | 
| 16 18 |  | 
| 17 19 | 
             
            module Puma
         | 
| 18 | 
            -
               | 
| 19 | 
            -
               | 
| 20 | 
            -
              autoload : | 
| 20 | 
            +
              # when Puma is loaded via `Puma::CLI`, all files are loaded via
         | 
| 21 | 
            +
              # `require_relative`.  The below are for non-standard loading
         | 
| 22 | 
            +
              autoload :Const,     "#{__dir__}/puma/const"
         | 
| 23 | 
            +
              autoload :Server,    "#{__dir__}/puma/server"
         | 
| 24 | 
            +
              autoload :Launcher,  "#{__dir__}/puma/launcher"
         | 
| 25 | 
            +
              autoload :LogWriter, "#{__dir__}/puma/log_writer"
         | 
| 21 26 |  | 
| 22 27 | 
             
              # at present, MiniSSL::Engine is only defined in extension code (puma_http11),
         | 
| 23 28 | 
             
              # not in minissl.rb
         | 
| @@ -26,7 +31,7 @@ module Puma | |
| 26 31 | 
             
              HAS_UNIX_SOCKET = Object.const_defined? :UNIXSocket
         | 
| 27 32 |  | 
| 28 33 | 
             
              if HAS_SSL
         | 
| 29 | 
            -
                 | 
| 34 | 
            +
                require_relative 'puma/minissl'
         | 
| 30 35 | 
             
              else
         | 
| 31 36 | 
             
                module MiniSSL
         | 
| 32 37 | 
             
                  # this class is defined so that it exists when Puma is compiled
         | 
| @@ -69,9 +74,7 @@ module Puma | |
| 69 74 | 
             
                @get_stats.stats
         | 
| 70 75 | 
             
              end
         | 
| 71 76 |  | 
| 72 | 
            -
              # Thread name is new in Ruby 2.3
         | 
| 73 77 | 
             
              def self.set_thread_name(name)
         | 
| 74 | 
            -
                return unless Thread.current.respond_to?(:name=)
         | 
| 75 78 | 
             
                Thread.current.name = "puma #{name}"
         | 
| 76 79 | 
             
              end
         | 
| 77 80 | 
             
            end
         |