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/launcher.rb
    CHANGED
    
    | @@ -1,11 +1,12 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 3 | 
            +
            require_relative 'log_writer'
         | 
| 4 | 
            +
            require_relative 'events'
         | 
| 5 | 
            +
            require_relative 'detect'
         | 
| 6 | 
            +
            require_relative 'cluster'
         | 
| 7 | 
            +
            require_relative 'single'
         | 
| 8 | 
            +
            require_relative 'const'
         | 
| 9 | 
            +
            require_relative 'binder'
         | 
| 9 10 |  | 
| 10 11 | 
             
            module Puma
         | 
| 11 12 | 
             
              # Puma::Launcher is the single entry point for starting a Puma server based on user
         | 
| @@ -15,18 +16,14 @@ module Puma | |
| 15 16 | 
             
              # It is responsible for either launching a cluster of Puma workers or a single
         | 
| 16 17 | 
             
              # puma server.
         | 
| 17 18 | 
             
              class Launcher
         | 
| 18 | 
            -
                 | 
| 19 | 
            -
             | 
| 20 | 
            -
                   :logger, :lowlevel_error_handler,
         | 
| 21 | 
            -
                   :before_worker_shutdown, :before_worker_boot, :before_worker_fork,
         | 
| 22 | 
            -
                   :after_worker_boot, :before_fork, :on_restart
         | 
| 23 | 
            -
                 ]
         | 
| 19 | 
            +
                autoload :BundlePruner, 'puma/launcher/bundle_pruner'
         | 
| 20 | 
            +
             | 
| 24 21 | 
             
                # Returns an instance of Launcher
         | 
| 25 22 | 
             
                #
         | 
| 26 23 | 
             
                # +conf+ A Puma::Configuration object indicating how to run the server.
         | 
| 27 24 | 
             
                #
         | 
| 28 25 | 
             
                # +launcher_args+ A Hash that currently has one required key `:events`,
         | 
| 29 | 
            -
                # this is expected to hold an object similar to an `Puma:: | 
| 26 | 
            +
                # this is expected to hold an object similar to an `Puma::LogWriter.stdio`,
         | 
| 30 27 | 
             
                # this object will be responsible for broadcasting Puma's internal state
         | 
| 31 28 | 
             
                # to a logging destination. An optional key `:argv` can be supplied,
         | 
| 32 29 | 
             
                # this should be an array of strings, these arguments are re-used when
         | 
| @@ -40,25 +37,28 @@ module Puma | |
| 40 37 | 
             
                #       [200, {}, ["hello world"]]
         | 
| 41 38 | 
             
                #     end
         | 
| 42 39 | 
             
                #   end
         | 
| 43 | 
            -
                #   Puma::Launcher.new(conf,  | 
| 40 | 
            +
                #   Puma::Launcher.new(conf, log_writer: Puma::LogWriter.stdio).run
         | 
| 44 41 | 
             
                def initialize(conf, launcher_args={})
         | 
| 45 42 | 
             
                  @runner        = nil
         | 
| 46 | 
            -
                  @ | 
| 43 | 
            +
                  @log_writer    = launcher_args[:log_writer] || LogWriter::DEFAULT
         | 
| 44 | 
            +
                  @events        = launcher_args[:events] || Events.new
         | 
| 47 45 | 
             
                  @argv          = launcher_args[:argv] || []
         | 
| 48 46 | 
             
                  @original_argv = @argv.dup
         | 
| 49 47 | 
             
                  @config        = conf
         | 
| 50 48 |  | 
| 51 | 
            -
                  @ | 
| 52 | 
            -
                  @binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
         | 
| 53 | 
            -
                  @binder.create_activated_fds(ENV).each { |k| ENV.delete k }
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                  @environment = conf.environment
         | 
| 49 | 
            +
                  @config.options[:log_writer] = @log_writer
         | 
| 56 50 |  | 
| 57 51 | 
             
                  # Advertise the Configuration
         | 
| 58 52 | 
             
                  Puma.cli_config = @config if defined?(Puma.cli_config)
         | 
| 59 53 |  | 
| 60 54 | 
             
                  @config.load
         | 
| 61 55 |  | 
| 56 | 
            +
                  @binder        = Binder.new(@log_writer, conf)
         | 
| 57 | 
            +
                  @binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
         | 
| 58 | 
            +
                  @binder.create_activated_fds(ENV).each { |k| ENV.delete k }
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  @environment = conf.environment
         | 
| 61 | 
            +
             | 
| 62 62 | 
             
                  if @config.options[:bind_to_activated_sockets]
         | 
| 63 63 | 
             
                    @config.options[:binds] = @binder.synthesize_binds_from_activated_fs(
         | 
| 64 64 | 
             
                      @config.options[:binds],
         | 
| @@ -69,8 +69,8 @@ module Puma | |
| 69 69 | 
             
                  @options = @config.options
         | 
| 70 70 | 
             
                  @config.clamp
         | 
| 71 71 |  | 
| 72 | 
            -
                  @ | 
| 73 | 
            -
                  @ | 
| 72 | 
            +
                  @log_writer.formatter = LogWriter::PidFormatter.new if clustered?
         | 
| 73 | 
            +
                  @log_writer.formatter = options[:log_formatter] if @options[:log_formatter]
         | 
| 74 74 |  | 
| 75 75 | 
             
                  generate_restart_data
         | 
| 76 76 |  | 
| @@ -80,17 +80,17 @@ module Puma | |
| 80 80 |  | 
| 81 81 | 
             
                  Dir.chdir(@restart_dir)
         | 
| 82 82 |  | 
| 83 | 
            -
                  prune_bundler | 
| 83 | 
            +
                  prune_bundler!
         | 
| 84 84 |  | 
| 85 85 | 
             
                  @environment = @options[:environment] if @options[:environment]
         | 
| 86 86 | 
             
                  set_rack_environment
         | 
| 87 87 |  | 
| 88 88 | 
             
                  if clustered?
         | 
| 89 | 
            -
                    @options[:logger] = @ | 
| 89 | 
            +
                    @options[:logger] = @log_writer
         | 
| 90 90 |  | 
| 91 | 
            -
                    @runner = Cluster.new(self | 
| 91 | 
            +
                    @runner = Cluster.new(self)
         | 
| 92 92 | 
             
                  else
         | 
| 93 | 
            -
                    @runner = Single.new(self | 
| 93 | 
            +
                    @runner = Single.new(self)
         | 
| 94 94 | 
             
                  end
         | 
| 95 95 | 
             
                  Puma.stats_object = @runner
         | 
| 96 96 |  | 
| @@ -99,7 +99,7 @@ module Puma | |
| 99 99 | 
             
                  log_config if ENV['PUMA_LOG_CONFIG']
         | 
| 100 100 | 
             
                end
         | 
| 101 101 |  | 
| 102 | 
            -
                attr_reader :binder, :events, :config, :options, :restart_dir
         | 
| 102 | 
            +
                attr_reader :binder, :log_writer, :events, :config, :options, :restart_dir
         | 
| 103 103 |  | 
| 104 104 | 
             
                # Return stats about the server
         | 
| 105 105 | 
             
                def stats
         | 
| @@ -115,7 +115,7 @@ module Puma | |
| 115 115 | 
             
                  permission = @options[:state_permission]
         | 
| 116 116 | 
             
                  return unless path
         | 
| 117 117 |  | 
| 118 | 
            -
                   | 
| 118 | 
            +
                  require_relative 'state_file'
         | 
| 119 119 |  | 
| 120 120 | 
             
                  sf = StateFile.new
         | 
| 121 121 | 
             
                  sf.pid = Process.pid
         | 
| @@ -159,18 +159,20 @@ module Puma | |
| 159 159 | 
             
                  true
         | 
| 160 160 | 
             
                end
         | 
| 161 161 |  | 
| 162 | 
            +
                # Begin a refork if supported
         | 
| 163 | 
            +
                def refork
         | 
| 164 | 
            +
                  if clustered? && @runner.respond_to?(:fork_worker!) && @options[:fork_worker]
         | 
| 165 | 
            +
                    @runner.fork_worker!
         | 
| 166 | 
            +
                    true
         | 
| 167 | 
            +
                  else
         | 
| 168 | 
            +
                    log "* refork called but not available."
         | 
| 169 | 
            +
                    false
         | 
| 170 | 
            +
                  end
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
             | 
| 162 173 | 
             
                # Run the server. This blocks until the server is stopped
         | 
| 163 174 | 
             
                def run
         | 
| 164 | 
            -
                  previous_env =
         | 
| 165 | 
            -
                    if defined?(Bundler)
         | 
| 166 | 
            -
                      env = Bundler::ORIGINAL_ENV.dup
         | 
| 167 | 
            -
                      # add -rbundler/setup so we load from Gemfile when restarting
         | 
| 168 | 
            -
                      bundle = "-rbundler/setup"
         | 
| 169 | 
            -
                      env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
         | 
| 170 | 
            -
                      env
         | 
| 171 | 
            -
                    else
         | 
| 172 | 
            -
                      ENV.to_h
         | 
| 173 | 
            -
                    end
         | 
| 175 | 
            +
                  previous_env = get_env
         | 
| 174 176 |  | 
| 175 177 | 
             
                  @config.clamp
         | 
| 176 178 |  | 
| @@ -179,23 +181,11 @@ module Puma | |
| 179 181 | 
             
                  setup_signals
         | 
| 180 182 | 
             
                  set_process_title
         | 
| 181 183 | 
             
                  integrate_with_systemd
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                  # This blocks until the server is stopped
         | 
| 182 186 | 
             
                  @runner.run
         | 
| 183 187 |  | 
| 184 | 
            -
                   | 
| 185 | 
            -
                  when :halt
         | 
| 186 | 
            -
                    log "* Stopping immediately!"
         | 
| 187 | 
            -
                    @runner.stop_control
         | 
| 188 | 
            -
                  when :run, :stop
         | 
| 189 | 
            -
                    graceful_stop
         | 
| 190 | 
            -
                  when :restart
         | 
| 191 | 
            -
                    log "* Restarting..."
         | 
| 192 | 
            -
                    ENV.replace(previous_env)
         | 
| 193 | 
            -
                    @runner.stop_control
         | 
| 194 | 
            -
                    restart!
         | 
| 195 | 
            -
                  when :exit
         | 
| 196 | 
            -
                    # nothing
         | 
| 197 | 
            -
                  end
         | 
| 198 | 
            -
                  close_binder_listeners unless @status == :restart
         | 
| 188 | 
            +
                  do_run_finished(previous_env)
         | 
| 199 189 | 
             
                end
         | 
| 200 190 |  | 
| 201 191 | 
             
                # Return all tcp ports the launcher may be using, TCP or SSL
         | 
| @@ -239,30 +229,56 @@ module Puma | |
| 239 229 |  | 
| 240 230 | 
             
                private
         | 
| 241 231 |  | 
| 242 | 
            -
                 | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
                   | 
| 250 | 
            -
                     | 
| 232 | 
            +
                def get_env
         | 
| 233 | 
            +
                  if defined?(Bundler)
         | 
| 234 | 
            +
                    env = Bundler::ORIGINAL_ENV.dup
         | 
| 235 | 
            +
                    # add -rbundler/setup so we load from Gemfile when restarting
         | 
| 236 | 
            +
                    bundle = "-rbundler/setup"
         | 
| 237 | 
            +
                    env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
         | 
| 238 | 
            +
                    env
         | 
| 239 | 
            +
                  else
         | 
| 240 | 
            +
                    ENV.to_h
         | 
| 251 241 | 
             
                  end
         | 
| 252 242 | 
             
                end
         | 
| 253 243 |  | 
| 254 | 
            -
                def  | 
| 255 | 
            -
                   | 
| 244 | 
            +
                def do_run_finished(previous_env)
         | 
| 245 | 
            +
                  case @status
         | 
| 246 | 
            +
                  when :halt
         | 
| 247 | 
            +
                    do_forceful_stop
         | 
| 248 | 
            +
                  when :run, :stop
         | 
| 249 | 
            +
                    do_graceful_stop
         | 
| 250 | 
            +
                  when :restart
         | 
| 251 | 
            +
                    do_restart(previous_env)
         | 
| 252 | 
            +
                  end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                  close_binder_listeners unless @status == :restart
         | 
| 255 | 
            +
                end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                def do_forceful_stop
         | 
| 258 | 
            +
                  log "* Stopping immediately!"
         | 
| 259 | 
            +
                  @runner.stop_control
         | 
| 260 | 
            +
                end
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                def do_graceful_stop
         | 
| 263 | 
            +
                  @events.fire_on_stopped!
         | 
| 264 | 
            +
                  @runner.stop_blocked
         | 
| 265 | 
            +
                end
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                def do_restart(previous_env)
         | 
| 268 | 
            +
                  log "* Restarting..."
         | 
| 269 | 
            +
                  ENV.replace(previous_env)
         | 
| 270 | 
            +
                  @runner.stop_control
         | 
| 271 | 
            +
                  restart!
         | 
| 256 272 | 
             
                end
         | 
| 257 273 |  | 
| 258 274 | 
             
                def restart!
         | 
| 259 275 | 
             
                  @events.fire_on_restart!
         | 
| 260 | 
            -
                  @config.run_hooks :on_restart, self, @ | 
| 276 | 
            +
                  @config.run_hooks :on_restart, self, @log_writer
         | 
| 261 277 |  | 
| 262 278 | 
             
                  if Puma.jruby?
         | 
| 263 279 | 
             
                    close_binder_listeners
         | 
| 264 280 |  | 
| 265 | 
            -
                     | 
| 281 | 
            +
                    require_relative 'jruby_restart'
         | 
| 266 282 | 
             
                    JRubyRestart.chdir_exec(@restart_dir, restart_args)
         | 
| 267 283 | 
             
                  elsif Puma.windows?
         | 
| 268 284 | 
             
                    close_binder_listeners
         | 
| @@ -279,72 +295,31 @@ module Puma | |
| 279 295 | 
             
                  end
         | 
| 280 296 | 
             
                end
         | 
| 281 297 |  | 
| 282 | 
            -
                #  | 
| 283 | 
            -
                 | 
| 284 | 
            -
             | 
| 285 | 
            -
             | 
| 286 | 
            -
                   | 
| 287 | 
            -
             | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 290 | 
            -
             | 
| 291 | 
            -
                  Array(@options[:extra_runtime_dependencies]).map do |d_name|
         | 
| 292 | 
            -
                    if (spec = spec_for_gem(d_name))
         | 
| 293 | 
            -
                      require_paths_for_gem(spec)
         | 
| 294 | 
            -
                    else
         | 
| 295 | 
            -
                      log "* Could not load extra dependency: #{d_name}"
         | 
| 296 | 
            -
                      nil
         | 
| 297 | 
            -
                    end
         | 
| 298 | 
            -
                  end.flatten.compact
         | 
| 299 | 
            -
                end
         | 
| 300 | 
            -
             | 
| 301 | 
            -
                # @!attribute [r] puma_wild_location
         | 
| 302 | 
            -
                def puma_wild_location
         | 
| 303 | 
            -
                  puma = spec_for_gem("puma")
         | 
| 304 | 
            -
                  dirs = require_paths_for_gem(puma)
         | 
| 305 | 
            -
                  puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
         | 
| 306 | 
            -
                  File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
         | 
| 307 | 
            -
                end
         | 
| 308 | 
            -
             | 
| 309 | 
            -
                def prune_bundler
         | 
| 310 | 
            -
                  return if ENV['PUMA_BUNDLER_PRUNED']
         | 
| 311 | 
            -
                  return unless defined?(Bundler)
         | 
| 312 | 
            -
                  require_rubygems_min_version!(Gem::Version.new("2.2"), "prune_bundler")
         | 
| 313 | 
            -
                  unless puma_wild_location
         | 
| 314 | 
            -
                    log "! Unable to prune Bundler environment, continuing"
         | 
| 315 | 
            -
                    return
         | 
| 298 | 
            +
                # If configured, write the pid of the current process out
         | 
| 299 | 
            +
                # to a file.
         | 
| 300 | 
            +
                def write_pid
         | 
| 301 | 
            +
                  path = @options[:pidfile]
         | 
| 302 | 
            +
                  return unless path
         | 
| 303 | 
            +
                  cur_pid = Process.pid
         | 
| 304 | 
            +
                  File.write path, cur_pid, mode: 'wb:UTF-8'
         | 
| 305 | 
            +
                  at_exit do
         | 
| 306 | 
            +
                    delete_pidfile if cur_pid == Process.pid
         | 
| 316 307 | 
             
                  end
         | 
| 308 | 
            +
                end
         | 
| 317 309 |  | 
| 318 | 
            -
             | 
| 319 | 
            -
             | 
| 320 | 
            -
                  log '* Pruning Bundler environment'
         | 
| 321 | 
            -
                  home = ENV['GEM_HOME']
         | 
| 322 | 
            -
                  bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
         | 
| 323 | 
            -
                  bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
         | 
| 324 | 
            -
                  with_unbundled_env do
         | 
| 325 | 
            -
                    ENV['GEM_HOME'] = home
         | 
| 326 | 
            -
                    ENV['BUNDLE_GEMFILE'] = bundle_gemfile
         | 
| 327 | 
            -
                    ENV['PUMA_BUNDLER_PRUNED'] = '1'
         | 
| 328 | 
            -
                    ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
         | 
| 329 | 
            -
                    args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
         | 
| 330 | 
            -
                    # Ruby 2.0+ defaults to true which breaks socket activation
         | 
| 331 | 
            -
                    args += [{:close_others => false}]
         | 
| 332 | 
            -
                    Kernel.exec(*args)
         | 
| 333 | 
            -
                  end
         | 
| 310 | 
            +
                def reload_worker_directory
         | 
| 311 | 
            +
                  @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
         | 
| 334 312 | 
             
                end
         | 
| 335 313 |  | 
| 336 | 
            -
                #
         | 
| 337 314 | 
             
                # Puma's systemd integration allows Puma to inform systemd:
         | 
| 338 315 | 
             
                #  1. when it has successfully started
         | 
| 339 316 | 
             
                #  2. when it is starting shutdown
         | 
| 340 317 | 
             
                #  3. periodically for a liveness check with a watchdog thread
         | 
| 341 | 
            -
                #
         | 
| 342 | 
            -
             | 
| 343 318 | 
             
                def integrate_with_systemd
         | 
| 344 319 | 
             
                  return unless ENV["NOTIFY_SOCKET"]
         | 
| 345 320 |  | 
| 346 321 | 
             
                  begin
         | 
| 347 | 
            -
                     | 
| 322 | 
            +
                    require_relative 'systemd'
         | 
| 348 323 | 
             
                  rescue LoadError
         | 
| 349 324 | 
             
                    log "Systemd integration failed. It looks like you're trying to use systemd notify but don't have sd_notify gem installed"
         | 
| 350 325 | 
             
                    return
         | 
| @@ -352,21 +327,13 @@ module Puma | |
| 352 327 |  | 
| 353 328 | 
             
                  log "* Enabling systemd notification integration"
         | 
| 354 329 |  | 
| 355 | 
            -
                  systemd = Systemd.new(@events)
         | 
| 330 | 
            +
                  systemd = Systemd.new(@log_writer, @events)
         | 
| 356 331 | 
             
                  systemd.hook_events
         | 
| 357 332 | 
             
                  systemd.start_watchdog
         | 
| 358 333 | 
             
                end
         | 
| 359 334 |  | 
| 360 | 
            -
                def spec_for_gem(gem_name)
         | 
| 361 | 
            -
                  Bundler.rubygems.loaded_specs(gem_name)
         | 
| 362 | 
            -
                end
         | 
| 363 | 
            -
             | 
| 364 | 
            -
                def require_paths_for_gem(gem_spec)
         | 
| 365 | 
            -
                  gem_spec.full_require_paths
         | 
| 366 | 
            -
                end
         | 
| 367 | 
            -
             | 
| 368 335 | 
             
                def log(str)
         | 
| 369 | 
            -
                  @ | 
| 336 | 
            +
                  @log_writer.log(str)
         | 
| 370 337 | 
             
                end
         | 
| 371 338 |  | 
| 372 339 | 
             
                def clustered?
         | 
| @@ -374,15 +341,10 @@ module Puma | |
| 374 341 | 
             
                end
         | 
| 375 342 |  | 
| 376 343 | 
             
                def unsupported(str)
         | 
| 377 | 
            -
                  @ | 
| 344 | 
            +
                  @log_writer.error(str)
         | 
| 378 345 | 
             
                  raise UnsupportedOption
         | 
| 379 346 | 
             
                end
         | 
| 380 347 |  | 
| 381 | 
            -
                def graceful_stop
         | 
| 382 | 
            -
                  @events.fire_on_stopped!
         | 
| 383 | 
            -
                  @runner.stop_blocked
         | 
| 384 | 
            -
                end
         | 
| 385 | 
            -
             | 
| 386 348 | 
             
                def set_process_title
         | 
| 387 349 | 
             
                  Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
         | 
| 388 350 | 
             
                end
         | 
| @@ -408,6 +370,11 @@ module Puma | |
| 408 370 | 
             
                  @options[:prune_bundler] && clustered? && !@options[:preload_app]
         | 
| 409 371 | 
             
                end
         | 
| 410 372 |  | 
| 373 | 
            +
                def prune_bundler!
         | 
| 374 | 
            +
                  return unless prune_bundler?
         | 
| 375 | 
            +
                  BundlePruner.new(@original_argv, @options[:extra_runtime_dependencies], @log_writer).prune
         | 
| 376 | 
            +
                end
         | 
| 377 | 
            +
             | 
| 411 378 | 
             
                def generate_restart_data
         | 
| 412 379 | 
             
                  if dir = @options[:directory]
         | 
| 413 380 | 
             
                    @restart_dir = dir
         | 
| @@ -474,7 +441,8 @@ module Puma | |
| 474 441 |  | 
| 475 442 | 
             
                  begin
         | 
| 476 443 | 
             
                    Signal.trap "SIGTERM" do
         | 
| 477 | 
            -
                       | 
| 444 | 
            +
                      # Shortcut the control flow in case raise_exception_on_sigterm is true
         | 
| 445 | 
            +
                      do_graceful_stop
         | 
| 478 446 |  | 
| 479 447 | 
             
                      raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
         | 
| 480 448 | 
             
                    end
         | 
| @@ -506,8 +474,8 @@ module Puma | |
| 506 474 | 
             
                    unless Puma.jruby? # INFO in use by JVM already
         | 
| 507 475 | 
             
                      Signal.trap "SIGINFO" do
         | 
| 508 476 | 
             
                        thread_status do |name, backtrace|
         | 
| 509 | 
            -
                          @ | 
| 510 | 
            -
                          @ | 
| 477 | 
            +
                          @log_writer.log(name)
         | 
| 478 | 
            +
                          @log_writer.log(backtrace.map { |bt| "  #{bt}" })
         | 
| 511 479 | 
             
                        end
         | 
| 512 480 | 
             
                      end
         | 
| 513 481 | 
             
                    end
         | 
| @@ -517,23 +485,6 @@ module Puma | |
| 517 485 | 
             
                  end
         | 
| 518 486 | 
             
                end
         | 
| 519 487 |  | 
| 520 | 
            -
                def require_rubygems_min_version!(min_version, feature)
         | 
| 521 | 
            -
                  return if min_version <= Gem::Version.new(Gem::VERSION)
         | 
| 522 | 
            -
             | 
| 523 | 
            -
                  raise "#{feature} is not supported on your version of RubyGems. " \
         | 
| 524 | 
            -
                          "You must have RubyGems #{min_version}+ to use this feature."
         | 
| 525 | 
            -
                end
         | 
| 526 | 
            -
             | 
| 527 | 
            -
                # @version 5.0.0
         | 
| 528 | 
            -
                def with_unbundled_env
         | 
| 529 | 
            -
                  bundler_ver = Gem::Version.new(Bundler::VERSION)
         | 
| 530 | 
            -
                  if bundler_ver < Gem::Version.new('2.1.0')
         | 
| 531 | 
            -
                    Bundler.with_clean_env { yield }
         | 
| 532 | 
            -
                  else
         | 
| 533 | 
            -
                    Bundler.with_unbundled_env { yield }
         | 
| 534 | 
            -
                  end
         | 
| 535 | 
            -
                end
         | 
| 536 | 
            -
             | 
| 537 488 | 
             
                def log_config
         | 
| 538 489 | 
             
                  log "Configuration:"
         | 
| 539 490 |  | 
| @@ -0,0 +1,137 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative 'null_io'
         | 
| 4 | 
            +
            require_relative 'error_logger'
         | 
| 5 | 
            +
            require 'stringio'
         | 
| 6 | 
            +
            require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Puma
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              # Handles logging concerns for both standard messages
         | 
| 11 | 
            +
              # (+stdout+) and errors (+stderr+).
         | 
| 12 | 
            +
              class LogWriter
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                class DefaultFormatter
         | 
| 15 | 
            +
                  def call(str)
         | 
| 16 | 
            +
                    str
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                class PidFormatter
         | 
| 21 | 
            +
                  def call(str)
         | 
| 22 | 
            +
                    "[#{$$}] #{str}"
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                LOG_QUEUE = Queue.new
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                attr_reader :stdout,
         | 
| 29 | 
            +
                            :stderr
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                attr_accessor :formatter
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # Create a LogWriter that prints to +stdout+ and +stderr+.
         | 
| 34 | 
            +
                def initialize(stdout, stderr)
         | 
| 35 | 
            +
                  @formatter = DefaultFormatter.new
         | 
| 36 | 
            +
                  @stdout = stdout
         | 
| 37 | 
            +
                  @stderr = stderr
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  @debug = ENV.key?('PUMA_DEBUG')
         | 
| 40 | 
            +
                  @error_logger = ErrorLogger.new(@stderr)
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                DEFAULT = new(STDOUT, STDERR)
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                # Returns an LogWriter object which writes its status to
         | 
| 46 | 
            +
                # two StringIO objects.
         | 
| 47 | 
            +
                def self.strings
         | 
| 48 | 
            +
                  LogWriter.new(StringIO.new, StringIO.new)
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def self.stdio
         | 
| 52 | 
            +
                  LogWriter.new($stdout, $stderr)
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def self.null
         | 
| 56 | 
            +
                  n = NullIO.new
         | 
| 57 | 
            +
                  LogWriter.new(n, n)
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                # Write +str+ to +@stdout+
         | 
| 61 | 
            +
                def log(str)
         | 
| 62 | 
            +
                  internal_write "#{@formatter.call str}\n"
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def write(str)
         | 
| 66 | 
            +
                  internal_write @formatter.call(str)
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                def internal_write(str)
         | 
| 70 | 
            +
                  LOG_QUEUE << str
         | 
| 71 | 
            +
                  while (w_str = LOG_QUEUE.pop(true)) do
         | 
| 72 | 
            +
                    begin
         | 
| 73 | 
            +
                      @stdout.is_a?(IO) and @stdout.wait_writable(1)
         | 
| 74 | 
            +
                      @stdout.write w_str
         | 
| 75 | 
            +
                      @stdout.flush unless @stdout.sync
         | 
| 76 | 
            +
                    rescue Errno::EPIPE, Errno::EBADF, IOError
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
                rescue ThreadError
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
                private :internal_write
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                def debug(str)
         | 
| 84 | 
            +
                  log("% #{str}") if @debug
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                # Write +str+ to +@stderr+
         | 
| 88 | 
            +
                def error(str)
         | 
| 89 | 
            +
                  @error_logger.info(text: @formatter.call("ERROR: #{str}"))
         | 
| 90 | 
            +
                  exit 1
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def format(str)
         | 
| 94 | 
            +
                  formatter.call(str)
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                # An HTTP connection error has occurred.
         | 
| 98 | 
            +
                # +error+ a connection exception, +req+ the request,
         | 
| 99 | 
            +
                # and +text+ additional info
         | 
| 100 | 
            +
                # @version 5.0.0
         | 
| 101 | 
            +
                def connection_error(error, req, text="HTTP connection error")
         | 
| 102 | 
            +
                  @error_logger.info(error: error, req: req, text: text)
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                # An HTTP parse error has occurred.
         | 
| 106 | 
            +
                # +error+ a parsing exception,
         | 
| 107 | 
            +
                # and +req+ the request.
         | 
| 108 | 
            +
                def parse_error(error, req)
         | 
| 109 | 
            +
                  @error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                # An SSL error has occurred.
         | 
| 113 | 
            +
                # @param error <Puma::MiniSSL::SSLError>
         | 
| 114 | 
            +
                # @param ssl_socket <Puma::MiniSSL::Socket>
         | 
| 115 | 
            +
                def ssl_error(error, ssl_socket)
         | 
| 116 | 
            +
                  peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
         | 
| 117 | 
            +
                  peercert = ssl_socket.peercert
         | 
| 118 | 
            +
                  subject = peercert ? peercert.subject : nil
         | 
| 119 | 
            +
                  @error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                # An unknown error has occurred.
         | 
| 123 | 
            +
                # +error+ an exception object, +req+ the request,
         | 
| 124 | 
            +
                # and +text+ additional info
         | 
| 125 | 
            +
                def unknown_error(error, req=nil, text="Unknown error")
         | 
| 126 | 
            +
                  @error_logger.info(error: error, req: req, text: text)
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                # Log occurred error debug dump.
         | 
| 130 | 
            +
                # +error+ an exception object, +req+ the request,
         | 
| 131 | 
            +
                # and +text+ additional info
         | 
| 132 | 
            +
                # @version 5.0.0
         | 
| 133 | 
            +
                def debug_error(error, req=nil, text="")
         | 
| 134 | 
            +
                  @error_logger.debug(error: error, req: req, text: text)
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
            end
         | 
| @@ -1,9 +1,9 @@ | |
| 1 1 | 
             
            module Puma
         | 
| 2 2 | 
             
              module MiniSSL
         | 
| 3 3 | 
             
                class ContextBuilder
         | 
| 4 | 
            -
                  def initialize(params,  | 
| 4 | 
            +
                  def initialize(params, log_writer)
         | 
| 5 5 | 
             
                    @params = params
         | 
| 6 | 
            -
                    @ | 
| 6 | 
            +
                    @log_writer = log_writer
         | 
| 7 7 | 
             
                  end
         | 
| 8 8 |  | 
| 9 9 | 
             
                  def context
         | 
| @@ -11,27 +11,36 @@ module Puma | |
| 11 11 |  | 
| 12 12 | 
             
                    if defined?(JRUBY_VERSION)
         | 
| 13 13 | 
             
                      unless params['keystore']
         | 
| 14 | 
            -
                         | 
| 14 | 
            +
                        log_writer.error "Please specify the Java keystore via 'keystore='"
         | 
| 15 15 | 
             
                      end
         | 
| 16 16 |  | 
| 17 17 | 
             
                      ctx.keystore = params['keystore']
         | 
| 18 18 |  | 
| 19 19 | 
             
                      unless params['keystore-pass']
         | 
| 20 | 
            -
                         | 
| 20 | 
            +
                        log_writer.error "Please specify the Java keystore password  via 'keystore-pass='"
         | 
| 21 21 | 
             
                      end
         | 
| 22 22 |  | 
| 23 23 | 
             
                      ctx.keystore_pass = params['keystore-pass']
         | 
| 24 | 
            -
                      ctx. | 
| 24 | 
            +
                      ctx.keystore_type = params['keystore-type']
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      if truststore = params['truststore']
         | 
| 27 | 
            +
                        ctx.truststore = truststore.eql?('default') ? :default : truststore
         | 
| 28 | 
            +
                        ctx.truststore_pass = params['truststore-pass']
         | 
| 29 | 
            +
                        ctx.truststore_type = params['truststore-type']
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                      ctx.cipher_suites = params['cipher_suites'] || params['ssl_cipher_list']
         | 
| 33 | 
            +
                      ctx.protocols = params['protocols'] if params['protocols']
         | 
| 25 34 | 
             
                    else
         | 
| 26 35 | 
             
                      if params['key'].nil? && params['key_pem'].nil?
         | 
| 27 | 
            -
                         | 
| 36 | 
            +
                        log_writer.error "Please specify the SSL key via 'key=' or 'key_pem='"
         | 
| 28 37 | 
             
                      end
         | 
| 29 38 |  | 
| 30 39 | 
             
                      ctx.key = params['key'] if params['key']
         | 
| 31 40 | 
             
                      ctx.key_pem = params['key_pem'] if params['key_pem']
         | 
| 32 41 |  | 
| 33 42 | 
             
                      if params['cert'].nil? && params['cert_pem'].nil?
         | 
| 34 | 
            -
                         | 
| 43 | 
            +
                        log_writer.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
         | 
| 35 44 | 
             
                      end
         | 
| 36 45 |  | 
| 37 46 | 
             
                      ctx.cert = params['cert'] if params['cert']
         | 
| @@ -39,16 +48,18 @@ module Puma | |
| 39 48 |  | 
| 40 49 | 
             
                      if ['peer', 'force_peer'].include?(params['verify_mode'])
         | 
| 41 50 | 
             
                        unless params['ca']
         | 
| 42 | 
            -
                           | 
| 51 | 
            +
                          log_writer.error "Please specify the SSL ca via 'ca='"
         | 
| 43 52 | 
             
                        end
         | 
| 44 53 | 
             
                      end
         | 
| 45 54 |  | 
| 46 55 | 
             
                      ctx.ca = params['ca'] if params['ca']
         | 
| 47 56 | 
             
                      ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                      ctx.reuse = params['reuse'] if params['reuse']
         | 
| 48 59 | 
             
                    end
         | 
| 49 60 |  | 
| 50 | 
            -
                    ctx.no_tlsv1 | 
| 51 | 
            -
                    ctx.no_tlsv1_1 =  | 
| 61 | 
            +
                    ctx.no_tlsv1   = params['no_tlsv1'] == 'true'
         | 
| 62 | 
            +
                    ctx.no_tlsv1_1 = params['no_tlsv1_1'] == 'true'
         | 
| 52 63 |  | 
| 53 64 | 
             
                    if params['verify_mode']
         | 
| 54 65 | 
             
                      ctx.verify_mode = case params['verify_mode']
         | 
| @@ -59,7 +70,7 @@ module Puma | |
| 59 70 | 
             
                                        when "none"
         | 
| 60 71 | 
             
                                          MiniSSL::VERIFY_NONE
         | 
| 61 72 | 
             
                                        else
         | 
| 62 | 
            -
                                           | 
| 73 | 
            +
                                          log_writer.error "Please specify a valid verify_mode="
         | 
| 63 74 | 
             
                                          MiniSSL::VERIFY_NONE
         | 
| 64 75 | 
             
                                        end
         | 
| 65 76 | 
             
                    end
         | 
| @@ -75,7 +86,7 @@ module Puma | |
| 75 86 |  | 
| 76 87 | 
             
                  private
         | 
| 77 88 |  | 
| 78 | 
            -
                  attr_reader :params, : | 
| 89 | 
            +
                  attr_reader :params, :log_writer
         | 
| 79 90 | 
             
                end
         | 
| 80 91 | 
             
              end
         | 
| 81 92 | 
             
            end
         |