puma 5.3.2 → 6.0.0
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 +284 -11
 - data/LICENSE +0 -0
 - data/README.md +61 -16
 - data/bin/puma-wild +1 -1
 - data/docs/architecture.md +49 -16
 - data/docs/compile_options.md +38 -2
 - data/docs/deployment.md +53 -67
 - data/docs/fork_worker.md +1 -3
 - data/docs/images/puma-connection-flow-no-reactor.png +0 -0
 - data/docs/images/puma-connection-flow.png +0 -0
 - data/docs/images/puma-general-arch.png +0 -0
 - data/docs/jungle/README.md +0 -0
 - data/docs/jungle/rc.d/README.md +0 -0
 - data/docs/jungle/rc.d/puma.conf +0 -0
 - data/docs/kubernetes.md +0 -0
 - data/docs/nginx.md +0 -0
 - data/docs/plugins.md +15 -15
 - data/docs/rails_dev_mode.md +2 -3
 - data/docs/restart.md +6 -6
 - data/docs/signals.md +11 -10
 - data/docs/stats.md +8 -8
 - data/docs/systemd.md +64 -67
 - data/docs/testing_benchmarks_local_files.md +150 -0
 - data/docs/testing_test_rackup_ci_files.md +36 -0
 - data/ext/puma_http11/PumaHttp11Service.java +0 -0
 - data/ext/puma_http11/ext_help.h +0 -0
 - data/ext/puma_http11/extconf.rb +44 -13
 - data/ext/puma_http11/http11_parser.c +24 -11
 - 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 +3 -3
 - data/ext/puma_http11/mini_ssl.c +122 -23
 - data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
 - data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
 - data/ext/puma_http11/org/jruby/puma/Http11Parser.java +50 -48
 - data/ext/puma_http11/org/jruby/puma/MiniSSL.java +188 -102
 - data/ext/puma_http11/puma_http11.c +18 -10
 - data/lib/puma/app/status.rb +9 -6
 - data/lib/puma/binder.rb +81 -42
 - data/lib/puma/cli.rb +23 -19
 - data/lib/puma/client.rb +124 -30
 - data/lib/puma/cluster/worker.rb +21 -29
 - data/lib/puma/cluster/worker_handle.rb +8 -1
 - data/lib/puma/cluster.rb +57 -48
 - data/lib/puma/commonlogger.rb +0 -0
 - data/lib/puma/configuration.rb +74 -55
 - data/lib/puma/const.rb +21 -24
 - data/lib/puma/control_cli.rb +22 -19
 - data/lib/puma/detect.rb +10 -2
 - data/lib/puma/dsl.rb +196 -57
 - 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/{json.rb → json_serialization.rb} +1 -1
 - data/lib/puma/launcher/bundle_pruner.rb +104 -0
 - data/lib/puma/launcher.rb +108 -154
 - data/lib/puma/log_writer.rb +137 -0
 - data/lib/puma/minissl/context_builder.rb +29 -16
 - data/lib/puma/minissl.rb +115 -38
 - data/lib/puma/null_io.rb +5 -0
 - data/lib/puma/plugin/tmp_restart.rb +1 -1
 - data/lib/puma/plugin.rb +2 -2
 - data/lib/puma/rack/builder.rb +5 -5
 - data/lib/puma/rack/urlmap.rb +0 -0
 - data/lib/puma/rack_default.rb +1 -1
 - data/lib/puma/reactor.rb +3 -3
 - data/lib/puma/request.rb +293 -153
 - data/lib/puma/runner.rb +63 -28
 - data/lib/puma/server.rb +83 -88
 - data/lib/puma/single.rb +10 -10
 - data/lib/puma/state_file.rb +39 -7
 - data/lib/puma/systemd.rb +3 -2
 - data/lib/puma/thread_pool.rb +22 -17
 - data/lib/puma/util.rb +20 -15
 - data/lib/puma.rb +12 -9
 - data/lib/rack/handler/puma.rb +9 -9
 - data/tools/Dockerfile +1 -1
 - data/tools/trickletest.rb +0 -0
 - metadata +13 -9
 - data/lib/puma/queue_close.rb +0 -26
 
    
        data/lib/puma/dsl.rb
    CHANGED
    
    | 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'const'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'util'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            module Puma
         
     | 
| 
       6 
7 
     | 
    
         
             
              # The methods that are available for use inside the configuration file.
         
     | 
| 
         @@ -31,8 +32,24 @@ module Puma 
     | 
|
| 
       31 
32 
     | 
    
         
             
              # You can also find many examples being used by the test suite in
         
     | 
| 
       32 
33 
     | 
    
         
             
              # +test/config+.
         
     | 
| 
       33 
34 
     | 
    
         
             
              #
         
     | 
| 
      
 35 
     | 
    
         
            +
              # Puma v6 adds the option to specify a key name (String or Symbol) to the
         
     | 
| 
      
 36 
     | 
    
         
            +
              # hooks that run inside the forked workers.  All the hooks run inside the
         
     | 
| 
      
 37 
     | 
    
         
            +
              # {Puma::Cluster::Worker#run} method.
         
     | 
| 
      
 38 
     | 
    
         
            +
              #
         
     | 
| 
      
 39 
     | 
    
         
            +
              # Previously, the worker index and the LogWriter instance were passed to the
         
     | 
| 
      
 40 
     | 
    
         
            +
              # hook blocks/procs.  If a key name is specified, a hash is passed as the last
         
     | 
| 
      
 41 
     | 
    
         
            +
              # parameter.  This allows storage of data, typically objects that are created
         
     | 
| 
      
 42 
     | 
    
         
            +
              # before the worker that need to be passed to the hook when the worker is shutdown.
         
     | 
| 
      
 43 
     | 
    
         
            +
              #
         
     | 
| 
      
 44 
     | 
    
         
            +
              # The following hooks have been updated:
         
     | 
| 
      
 45 
     | 
    
         
            +
              #
         
     | 
| 
      
 46 
     | 
    
         
            +
              #     | DSL Method         |  Options Key            | Fork Block Location |
         
     | 
| 
      
 47 
     | 
    
         
            +
              #     | on_worker_boot     | :before_worker_boot     | inside, before      |
         
     | 
| 
      
 48 
     | 
    
         
            +
              #     | on_worker_shutdown | :before_worker_shutdown | inside, after       |
         
     | 
| 
      
 49 
     | 
    
         
            +
              #     | on_refork          | :before_refork          | inside              |
         
     | 
| 
      
 50 
     | 
    
         
            +
              #
         
     | 
| 
       34 
51 
     | 
    
         
             
              class DSL
         
     | 
| 
       35 
     | 
    
         
            -
                 
     | 
| 
      
 52 
     | 
    
         
            +
                ON_WORKER_KEY = [String, Symbol].freeze
         
     | 
| 
       36 
53 
     | 
    
         | 
| 
       37 
54 
     | 
    
         
             
                # convenience method so logic can be used in CI
         
     | 
| 
       38 
55 
     | 
    
         
             
                # @see ssl_bind
         
     | 
| 
         @@ -46,25 +63,58 @@ module Puma 
     | 
|
| 
       46 
63 
     | 
    
         
             
                    else ''
         
     | 
| 
       47 
64 
     | 
    
         
             
                    end
         
     | 
| 
       48 
65 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
                  ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
         
     | 
| 
       50 
69 
     | 
    
         | 
| 
       51 
70 
     | 
    
         
             
                  if defined?(JRUBY_VERSION)
         
     | 
| 
       52 
     | 
    
         
            -
                     
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
      
 71 
     | 
    
         
            +
                    cipher_suites = opts[:ssl_cipher_list] ? "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil # old name
         
     | 
| 
      
 72 
     | 
    
         
            +
                    cipher_suites = "#{cipher_suites}&cipher_suites=#{opts[:cipher_suites]}" if opts[:cipher_suites]
         
     | 
| 
      
 73 
     | 
    
         
            +
                    protocols = opts[:protocols] ? "&protocols=#{opts[:protocols]}" : nil
         
     | 
| 
       54 
74 
     | 
    
         | 
| 
       55 
75 
     | 
    
         
             
                    keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
         
     | 
| 
      
 76 
     | 
    
         
            +
                    keystore_additions = "#{keystore_additions}&keystore-type=#{opts[:keystore_type]}" if opts[:keystore_type]
         
     | 
| 
      
 77 
     | 
    
         
            +
                    if opts[:truststore]
         
     | 
| 
      
 78 
     | 
    
         
            +
                      truststore_additions = "&truststore=#{opts[:truststore]}"
         
     | 
| 
      
 79 
     | 
    
         
            +
                      truststore_additions = "#{truststore_additions}&truststore-pass=#{opts[:truststore_pass]}" if opts[:truststore_pass]
         
     | 
| 
      
 80 
     | 
    
         
            +
                      truststore_additions = "#{truststore_additions}&truststore-type=#{opts[:truststore_type]}" if opts[:truststore_type]
         
     | 
| 
      
 81 
     | 
    
         
            +
                    end
         
     | 
| 
       56 
82 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                    "ssl://#{host}:#{port}?#{keystore_additions}#{ 
     | 
| 
       58 
     | 
    
         
            -
                      "&verify_mode=#{verify}#{tls_str}#{ca_additions}"
         
     | 
| 
      
 83 
     | 
    
         
            +
                    "ssl://#{host}:#{port}?#{keystore_additions}#{truststore_additions}#{cipher_suites}#{protocols}" \
         
     | 
| 
      
 84 
     | 
    
         
            +
                      "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
         
     | 
| 
       59 
85 
     | 
    
         
             
                  else
         
     | 
| 
       60 
     | 
    
         
            -
                    ssl_cipher_filter = opts[:ssl_cipher_filter] ?
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                     
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 86 
     | 
    
         
            +
                    ssl_cipher_filter = opts[:ssl_cipher_filter] ? "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
         
     | 
| 
      
 87 
     | 
    
         
            +
                    v_flags = (ary = opts[:verification_flags]) ? "&verification_flags=#{Array(ary).join ','}" : nil
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(cert)}" : nil
         
     | 
| 
      
 90 
     | 
    
         
            +
                    key_flags = (key = opts[:key]) ? "&key=#{Puma::Util.escape(key)}" : nil
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    reuse_flag =
         
     | 
| 
      
 93 
     | 
    
         
            +
                      if (reuse = opts[:reuse])
         
     | 
| 
      
 94 
     | 
    
         
            +
                        if reuse == true
         
     | 
| 
      
 95 
     | 
    
         
            +
                          '&reuse=dflt'
         
     | 
| 
      
 96 
     | 
    
         
            +
                        elsif reuse.is_a?(Hash) && (reuse.key?(:size) || reuse.key?(:timeout))
         
     | 
| 
      
 97 
     | 
    
         
            +
                          val = +''
         
     | 
| 
      
 98 
     | 
    
         
            +
                          if (size = reuse[:size]) && Integer === size
         
     | 
| 
      
 99 
     | 
    
         
            +
                            val << size.to_s
         
     | 
| 
      
 100 
     | 
    
         
            +
                          end
         
     | 
| 
      
 101 
     | 
    
         
            +
                          if (timeout = reuse[:timeout]) && Integer === timeout
         
     | 
| 
      
 102 
     | 
    
         
            +
                            val << ",#{timeout}"
         
     | 
| 
      
 103 
     | 
    
         
            +
                          end
         
     | 
| 
      
 104 
     | 
    
         
            +
                          if val.empty?
         
     | 
| 
      
 105 
     | 
    
         
            +
                            nil
         
     | 
| 
      
 106 
     | 
    
         
            +
                          else
         
     | 
| 
      
 107 
     | 
    
         
            +
                            "&reuse=#{val}"
         
     | 
| 
      
 108 
     | 
    
         
            +
                          end
         
     | 
| 
      
 109 
     | 
    
         
            +
                        else
         
     | 
| 
      
 110 
     | 
    
         
            +
                          nil
         
     | 
| 
      
 111 
     | 
    
         
            +
                        end
         
     | 
| 
      
 112 
     | 
    
         
            +
                      else
         
     | 
| 
      
 113 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 114 
     | 
    
         
            +
                      end
         
     | 
| 
       65 
115 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                    "ssl://#{host}:#{port} 
     | 
| 
       67 
     | 
    
         
            -
                      "#{ 
     | 
| 
      
 116 
     | 
    
         
            +
                    "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{ssl_cipher_filter}" \
         
     | 
| 
      
 117 
     | 
    
         
            +
                      "#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
         
     | 
| 
       68 
118 
     | 
    
         
             
                  end
         
     | 
| 
       69 
119 
     | 
    
         
             
                end
         
     | 
| 
       70 
120 
     | 
    
         | 
| 
         @@ -100,7 +150,7 @@ module Puma 
     | 
|
| 
       100 
150 
     | 
    
         
             
                end
         
     | 
| 
       101 
151 
     | 
    
         | 
| 
       102 
152 
     | 
    
         
             
                def default_host
         
     | 
| 
       103 
     | 
    
         
            -
                  @options[:default_host] || Configuration:: 
     | 
| 
      
 153 
     | 
    
         
            +
                  @options[:default_host] || Configuration::DEFAULTS[:tcp_host]
         
     | 
| 
       104 
154 
     | 
    
         
             
                end
         
     | 
| 
       105 
155 
     | 
    
         | 
| 
       106 
156 
     | 
    
         
             
                def inject(&blk)
         
     | 
| 
         @@ -191,7 +241,7 @@ module Puma 
     | 
|
| 
       191 
241 
     | 
    
         
             
                end
         
     | 
| 
       192 
242 
     | 
    
         | 
| 
       193 
243 
     | 
    
         
             
                # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
         
     | 
| 
       194 
     | 
    
         
            -
                # accepted protocols. Multiple urls can be bound to, calling  
     | 
| 
      
 244 
     | 
    
         
            +
                # accepted protocols. Multiple urls can be bound to, calling +bind+ does
         
     | 
| 
       195 
245 
     | 
    
         
             
                # not overwrite previous bindings.
         
     | 
| 
       196 
246 
     | 
    
         
             
                #
         
     | 
| 
       197 
247 
     | 
    
         
             
                # The default is "tcp://0.0.0.0:9292".
         
     | 
| 
         @@ -381,6 +431,13 @@ module Puma 
     | 
|
| 
       381 
431 
     | 
    
         
             
                  @options[:rackup] ||= path.to_s
         
     | 
| 
       382 
432 
     | 
    
         
             
                end
         
     | 
| 
       383 
433 
     | 
    
         | 
| 
      
 434 
     | 
    
         
            +
                # Allows setting `env['rack.url_scheme']`.
         
     | 
| 
      
 435 
     | 
    
         
            +
                # Only necessary if X-Forwarded-Proto is not being set by your proxy
         
     | 
| 
      
 436 
     | 
    
         
            +
                # Normal values are 'http' or 'https'.
         
     | 
| 
      
 437 
     | 
    
         
            +
                def rack_url_scheme(scheme=nil)
         
     | 
| 
      
 438 
     | 
    
         
            +
                  @options[:rack_url_scheme] = scheme
         
     | 
| 
      
 439 
     | 
    
         
            +
                end
         
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
       384 
441 
     | 
    
         
             
                def early_hints(answer=true)
         
     | 
| 
       385 
442 
     | 
    
         
             
                  @options[:early_hints] = answer
         
     | 
| 
       386 
443 
     | 
    
         
             
                end
         
     | 
| 
         @@ -429,8 +486,19 @@ module Puma 
     | 
|
| 
       429 
486 
     | 
    
         
             
                  @options[:max_threads] = max
         
     | 
| 
       430 
487 
     | 
    
         
             
                end
         
     | 
| 
       431 
488 
     | 
    
         | 
| 
       432 
     | 
    
         
            -
                # Instead of  
     | 
| 
       433 
     | 
    
         
            -
                # 
     | 
| 
      
 489 
     | 
    
         
            +
                # Instead of using +bind+ and manually constructing a URI like:
         
     | 
| 
      
 490 
     | 
    
         
            +
                #
         
     | 
| 
      
 491 
     | 
    
         
            +
                #    bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
         
     | 
| 
      
 492 
     | 
    
         
            +
                #
         
     | 
| 
      
 493 
     | 
    
         
            +
                # you can use the this method.
         
     | 
| 
      
 494 
     | 
    
         
            +
                #
         
     | 
| 
      
 495 
     | 
    
         
            +
                # When binding on localhost you don't need to specify +cert+ and +key+,
         
     | 
| 
      
 496 
     | 
    
         
            +
                # Puma will assume you are using the +localhost+ gem and try to load the
         
     | 
| 
      
 497 
     | 
    
         
            +
                # appropriate files.
         
     | 
| 
      
 498 
     | 
    
         
            +
                #
         
     | 
| 
      
 499 
     | 
    
         
            +
                # When using the options hash parameter, the `reuse:` value is either
         
     | 
| 
      
 500 
     | 
    
         
            +
                # `true`, which sets reuse 'on' with default values, or a hash, with `:size`
         
     | 
| 
      
 501 
     | 
    
         
            +
                # and/or `:timeout` keys, each with integer values.
         
     | 
| 
       434 
502 
     | 
    
         
             
                #
         
     | 
| 
       435 
503 
     | 
    
         
             
                # @example
         
     | 
| 
       436 
504 
     | 
    
         
             
                #   ssl_bind '127.0.0.1', '9292', {
         
     | 
| 
         @@ -439,15 +507,28 @@ module Puma 
     | 
|
| 
       439 
507 
     | 
    
         
             
                #     ssl_cipher_filter: cipher_filter, # optional
         
     | 
| 
       440 
508 
     | 
    
         
             
                #     verify_mode: verify_mode,         # default 'none'
         
     | 
| 
       441 
509 
     | 
    
         
             
                #     verification_flags: flags,        # optional, not supported by JRuby
         
     | 
| 
      
 510 
     | 
    
         
            +
                #     reuse: true                       # optional
         
     | 
| 
       442 
511 
     | 
    
         
             
                #   }
         
     | 
| 
       443 
     | 
    
         
            -
                # 
     | 
| 
      
 512 
     | 
    
         
            +
                #
         
     | 
| 
      
 513 
     | 
    
         
            +
                # @example Using self-signed certificate with the +localhost+ gem:
         
     | 
| 
      
 514 
     | 
    
         
            +
                #   ssl_bind '127.0.0.1', '9292'
         
     | 
| 
      
 515 
     | 
    
         
            +
                #
         
     | 
| 
      
 516 
     | 
    
         
            +
                # @example Alternatively, you can provide +cert_pem+ and +key_pem+:
         
     | 
| 
      
 517 
     | 
    
         
            +
                #   ssl_bind '127.0.0.1', '9292', {
         
     | 
| 
      
 518 
     | 
    
         
            +
                #     cert_pem: File.read(path_to_cert),
         
     | 
| 
      
 519 
     | 
    
         
            +
                #     key_pem: File.read(path_to_key),
         
     | 
| 
      
 520 
     | 
    
         
            +
                #     reuse: {size: 2_000, timeout: 20} # optional
         
     | 
| 
      
 521 
     | 
    
         
            +
                #   }
         
     | 
| 
      
 522 
     | 
    
         
            +
                #
         
     | 
| 
      
 523 
     | 
    
         
            +
                # @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
         
     | 
| 
       444 
524 
     | 
    
         
             
                #   ssl_bind '127.0.0.1', '9292', {
         
     | 
| 
       445 
525 
     | 
    
         
             
                #     keystore: path_to_keystore,
         
     | 
| 
       446 
526 
     | 
    
         
             
                #     keystore_pass: password,
         
     | 
| 
       447 
527 
     | 
    
         
             
                #     ssl_cipher_list: cipher_list,     # optional
         
     | 
| 
       448 
528 
     | 
    
         
             
                #     verify_mode: verify_mode          # default 'none'
         
     | 
| 
       449 
529 
     | 
    
         
             
                #   }
         
     | 
| 
       450 
     | 
    
         
            -
                def ssl_bind(host, port, opts)
         
     | 
| 
      
 530 
     | 
    
         
            +
                def ssl_bind(host, port, opts = {})
         
     | 
| 
      
 531 
     | 
    
         
            +
                  add_pem_values_to_options_store(opts)
         
     | 
| 
       451 
532 
     | 
    
         
             
                  bind self.class.ssl_bind_str(host, port, opts)
         
     | 
| 
       452 
533 
     | 
    
         
             
                end
         
     | 
| 
       453 
534 
     | 
    
         | 
| 
         @@ -529,9 +610,8 @@ module Puma 
     | 
|
| 
       529 
610 
     | 
    
         
             
                #   on_worker_boot do
         
     | 
| 
       530 
611 
     | 
    
         
             
                #     puts 'Before worker boot...'
         
     | 
| 
       531 
612 
     | 
    
         
             
                #   end
         
     | 
| 
       532 
     | 
    
         
            -
                def on_worker_boot(&block)
         
     | 
| 
       533 
     | 
    
         
            -
                   
     | 
| 
       534 
     | 
    
         
            -
                  @options[:before_worker_boot] << block
         
     | 
| 
      
 613 
     | 
    
         
            +
                def on_worker_boot(key = nil, &block)
         
     | 
| 
      
 614 
     | 
    
         
            +
                  process_hook :before_worker_boot, key, block, 'on_worker_boot'
         
     | 
| 
       535 
615 
     | 
    
         
             
                end
         
     | 
| 
       536 
616 
     | 
    
         | 
| 
       537 
617 
     | 
    
         
             
                # Code to run immediately before a worker shuts
         
     | 
| 
         @@ -546,9 +626,8 @@ module Puma 
     | 
|
| 
       546 
626 
     | 
    
         
             
                #   on_worker_shutdown do
         
     | 
| 
       547 
627 
     | 
    
         
             
                #     puts 'On worker shutdown...'
         
     | 
| 
       548 
628 
     | 
    
         
             
                #   end
         
     | 
| 
       549 
     | 
    
         
            -
                def on_worker_shutdown(&block)
         
     | 
| 
       550 
     | 
    
         
            -
                   
     | 
| 
       551 
     | 
    
         
            -
                  @options[:before_worker_shutdown] << block
         
     | 
| 
      
 629 
     | 
    
         
            +
                def on_worker_shutdown(key = nil, &block)
         
     | 
| 
      
 630 
     | 
    
         
            +
                  process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
         
     | 
| 
       552 
631 
     | 
    
         
             
                end
         
     | 
| 
       553 
632 
     | 
    
         | 
| 
       554 
633 
     | 
    
         
             
                # Code to run in the master right before a worker is started. The worker's
         
     | 
| 
         @@ -562,8 +641,7 @@ module Puma 
     | 
|
| 
       562 
641 
     | 
    
         
             
                #     puts 'Before worker fork...'
         
     | 
| 
       563 
642 
     | 
    
         
             
                #   end
         
     | 
| 
       564 
643 
     | 
    
         
             
                def on_worker_fork(&block)
         
     | 
| 
       565 
     | 
    
         
            -
                   
     | 
| 
       566 
     | 
    
         
            -
                  @options[:before_worker_fork] << block
         
     | 
| 
      
 644 
     | 
    
         
            +
                  process_hook :before_worker_fork, nil, block, 'on_worker_fork'
         
     | 
| 
       567 
645 
     | 
    
         
             
                end
         
     | 
| 
       568 
646 
     | 
    
         | 
| 
       569 
647 
     | 
    
         
             
                # Code to run in the master after a worker has been started. The worker's
         
     | 
| 
         @@ -577,8 +655,7 @@ module Puma 
     | 
|
| 
       577 
655 
     | 
    
         
             
                #     puts 'After worker fork...'
         
     | 
| 
       578 
656 
     | 
    
         
             
                #   end
         
     | 
| 
       579 
657 
     | 
    
         
             
                def after_worker_fork(&block)
         
     | 
| 
       580 
     | 
    
         
            -
                   
     | 
| 
       581 
     | 
    
         
            -
                  @options[:after_worker_fork] = block
         
     | 
| 
      
 658 
     | 
    
         
            +
                  process_hook :after_worker_fork, nil, block, 'after_worker_fork'
         
     | 
| 
       582 
659 
     | 
    
         
             
                end
         
     | 
| 
       583 
660 
     | 
    
         | 
| 
       584 
661 
     | 
    
         
             
                alias_method :after_worker_boot, :after_worker_fork
         
     | 
| 
         @@ -601,9 +678,8 @@ module Puma 
     | 
|
| 
       601 
678 
     | 
    
         
             
                #   end
         
     | 
| 
       602 
679 
     | 
    
         
             
                # @version 5.0.0
         
     | 
| 
       603 
680 
     | 
    
         
             
                #
         
     | 
| 
       604 
     | 
    
         
            -
                def on_refork(&block)
         
     | 
| 
       605 
     | 
    
         
            -
                   
     | 
| 
       606 
     | 
    
         
            -
                  @options[:before_refork] << block
         
     | 
| 
      
 681 
     | 
    
         
            +
                def on_refork(key = nil, &block)
         
     | 
| 
      
 682 
     | 
    
         
            +
                  process_hook :before_refork, key, block, 'on_refork'
         
     | 
| 
       607 
683 
     | 
    
         
             
                end
         
     | 
| 
       608 
684 
     | 
    
         | 
| 
       609 
685 
     | 
    
         
             
                # Code to run out-of-band when the worker is idle.
         
     | 
| 
         @@ -616,8 +692,7 @@ module Puma 
     | 
|
| 
       616 
692 
     | 
    
         
             
                #
         
     | 
| 
       617 
693 
     | 
    
         
             
                # This can be called multiple times to add several hooks.
         
     | 
| 
       618 
694 
     | 
    
         
             
                def out_of_band(&block)
         
     | 
| 
       619 
     | 
    
         
            -
                   
     | 
| 
       620 
     | 
    
         
            -
                  @options[:out_of_band] << block
         
     | 
| 
      
 695 
     | 
    
         
            +
                  process_hook :out_of_band, nil, block, 'out_of_band'
         
     | 
| 
       621 
696 
     | 
    
         
             
                end
         
     | 
| 
       622 
697 
     | 
    
         | 
| 
       623 
698 
     | 
    
         
             
                # The directory to operate out of.
         
     | 
| 
         @@ -720,6 +795,19 @@ module Puma 
     | 
|
| 
       720 
795 
     | 
    
         
             
                  @options[:tag] = string.to_s
         
     | 
| 
       721 
796 
     | 
    
         
             
                end
         
     | 
| 
       722 
797 
     | 
    
         | 
| 
      
 798 
     | 
    
         
            +
                # Change the default interval for checking workers.
         
     | 
| 
      
 799 
     | 
    
         
            +
                #
         
     | 
| 
      
 800 
     | 
    
         
            +
                # The default value is 5 seconds.
         
     | 
| 
      
 801 
     | 
    
         
            +
                #
         
     | 
| 
      
 802 
     | 
    
         
            +
                # @note Cluster mode only.
         
     | 
| 
      
 803 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 804 
     | 
    
         
            +
                #   worker_check_interval 5
         
     | 
| 
      
 805 
     | 
    
         
            +
                # @see Puma::Cluster#check_workers
         
     | 
| 
      
 806 
     | 
    
         
            +
                #
         
     | 
| 
      
 807 
     | 
    
         
            +
                def worker_check_interval(interval)
         
     | 
| 
      
 808 
     | 
    
         
            +
                  @options[:worker_check_interval] = Integer(interval)
         
     | 
| 
      
 809 
     | 
    
         
            +
                end
         
     | 
| 
      
 810 
     | 
    
         
            +
             
     | 
| 
       723 
811 
     | 
    
         
             
                # Verifies that all workers have checked in to the master process within
         
     | 
| 
       724 
812 
     | 
    
         
             
                # the given timeout. If not the worker process will be restarted. This is
         
     | 
| 
       725 
813 
     | 
    
         
             
                # not a request timeout, it is to protect against a hung or dead process.
         
     | 
| 
         @@ -734,7 +822,7 @@ module Puma 
     | 
|
| 
       734 
822 
     | 
    
         
             
                #
         
     | 
| 
       735 
823 
     | 
    
         
             
                def worker_timeout(timeout)
         
     | 
| 
       736 
824 
     | 
    
         
             
                  timeout = Integer(timeout)
         
     | 
| 
       737 
     | 
    
         
            -
                  min =  
     | 
| 
      
 825 
     | 
    
         
            +
                  min = @options.fetch(:worker_check_interval, Configuration::DEFAULTS[:worker_check_interval])
         
     | 
| 
       738 
826 
     | 
    
         | 
| 
       739 
827 
     | 
    
         
             
                  if timeout <= min
         
     | 
| 
       740 
828 
     | 
    
         
             
                    raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
         
     | 
| 
         @@ -766,6 +854,30 @@ module Puma 
     | 
|
| 
       766 
854 
     | 
    
         
             
                  @options[:worker_shutdown_timeout] = Integer(timeout)
         
     | 
| 
       767 
855 
     | 
    
         
             
                end
         
     | 
| 
       768 
856 
     | 
    
         | 
| 
      
 857 
     | 
    
         
            +
                # Set the strategy for worker culling.
         
     | 
| 
      
 858 
     | 
    
         
            +
                #
         
     | 
| 
      
 859 
     | 
    
         
            +
                # There are two possible values:
         
     | 
| 
      
 860 
     | 
    
         
            +
                #
         
     | 
| 
      
 861 
     | 
    
         
            +
                # 1. **:youngest** - the youngest workers (i.e. the workers that were
         
     | 
| 
      
 862 
     | 
    
         
            +
                #    the most recently started) will be culled.
         
     | 
| 
      
 863 
     | 
    
         
            +
                # 2. **:oldest** - the oldest workers (i.e. the workers that were started
         
     | 
| 
      
 864 
     | 
    
         
            +
                #    the longest time ago) will be culled.
         
     | 
| 
      
 865 
     | 
    
         
            +
                #
         
     | 
| 
      
 866 
     | 
    
         
            +
                # @note Cluster mode only.
         
     | 
| 
      
 867 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 868 
     | 
    
         
            +
                #   worker_culling_strategy :oldest
         
     | 
| 
      
 869 
     | 
    
         
            +
                # @see Puma::Cluster#cull_workers
         
     | 
| 
      
 870 
     | 
    
         
            +
                #
         
     | 
| 
      
 871 
     | 
    
         
            +
                def worker_culling_strategy(strategy)
         
     | 
| 
      
 872 
     | 
    
         
            +
                  stategy = strategy.to_sym
         
     | 
| 
      
 873 
     | 
    
         
            +
             
     | 
| 
      
 874 
     | 
    
         
            +
                  if ![:youngest, :oldest].include?(strategy)
         
     | 
| 
      
 875 
     | 
    
         
            +
                    raise "Invalid value for worker_culling_strategy - #{stategy}"
         
     | 
| 
      
 876 
     | 
    
         
            +
                  end
         
     | 
| 
      
 877 
     | 
    
         
            +
             
     | 
| 
      
 878 
     | 
    
         
            +
                  @options[:worker_culling_strategy] = strategy
         
     | 
| 
      
 879 
     | 
    
         
            +
                end
         
     | 
| 
      
 880 
     | 
    
         
            +
             
     | 
| 
       769 
881 
     | 
    
         
             
                # When set to true (the default), workers accept all requests
         
     | 
| 
       770 
882 
     | 
    
         
             
                # and queue them before passing them to the handlers.
         
     | 
| 
       771 
883 
     | 
    
         
             
                # When set to false, each worker process accepts exactly as
         
     | 
| 
         @@ -811,17 +923,23 @@ module Puma 
     | 
|
| 
       811 
923 
     | 
    
         
             
                # a kernel syscall is required which for very fast rack handlers
         
     | 
| 
       812 
924 
     | 
    
         
             
                # slows down the handling significantly.
         
     | 
| 
       813 
925 
     | 
    
         
             
                #
         
     | 
| 
       814 
     | 
    
         
            -
                # There are  
     | 
| 
      
 926 
     | 
    
         
            +
                # There are 5 possible values:
         
     | 
| 
       815 
927 
     | 
    
         
             
                #
         
     | 
| 
       816 
928 
     | 
    
         
             
                # 1. **:socket** (the default) - read the peername from the socket using the
         
     | 
| 
       817 
     | 
    
         
            -
                #    syscall. This is the normal behavior.
         
     | 
| 
      
 929 
     | 
    
         
            +
                #    syscall. This is the normal behavior. If this fails for any reason (e.g.,
         
     | 
| 
      
 930 
     | 
    
         
            +
                #    if the peer disconnects between the connection being accepted and the getpeername
         
     | 
| 
      
 931 
     | 
    
         
            +
                #    system call), Puma will return "0.0.0.0"
         
     | 
| 
       818 
932 
     | 
    
         
             
                # 2. **:localhost** - set the remote address to "127.0.0.1"
         
     | 
| 
       819 
933 
     | 
    
         
             
                # 3. **header: <http_header>**- set the remote address to the value of the
         
     | 
| 
       820 
934 
     | 
    
         
             
                #    provided http header. For instance:
         
     | 
| 
       821 
935 
     | 
    
         
             
                #    `set_remote_address header: "X-Real-IP"`.
         
     | 
| 
       822 
936 
     | 
    
         
             
                #    Only the first word (as separated by spaces or comma) is used, allowing
         
     | 
| 
       823 
     | 
    
         
            -
                #    headers such as X-Forwarded-For to be used as well.
         
     | 
| 
       824 
     | 
    
         
            -
                #  
     | 
| 
      
 937 
     | 
    
         
            +
                #    headers such as X-Forwarded-For to be used as well. If this header is absent,
         
     | 
| 
      
 938 
     | 
    
         
            +
                #    Puma will fall back to the behavior of :socket
         
     | 
| 
      
 939 
     | 
    
         
            +
                # 4. **proxy_protocol: :v1**- set the remote address to the value read from the
         
     | 
| 
      
 940 
     | 
    
         
            +
                #    HAproxy PROXY protocol, version 1. If the request does not have the PROXY
         
     | 
| 
      
 941 
     | 
    
         
            +
                #    protocol attached to it, will fall back to :socket
         
     | 
| 
      
 942 
     | 
    
         
            +
                # 5. **\<Any string\>** - this allows you to hardcode remote address to any value
         
     | 
| 
       825 
943 
     | 
    
         
             
                #    you wish. Because Puma never uses this field anyway, it's format is
         
     | 
| 
       826 
944 
     | 
    
         
             
                #    entirely in your hands.
         
     | 
| 
       827 
945 
     | 
    
         
             
                #
         
     | 
| 
         @@ -839,6 +957,13 @@ module Puma 
     | 
|
| 
       839 
957 
     | 
    
         
             
                    if hdr = val[:header]
         
     | 
| 
       840 
958 
     | 
    
         
             
                      @options[:remote_address] = :header
         
     | 
| 
       841 
959 
     | 
    
         
             
                      @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
         
     | 
| 
      
 960 
     | 
    
         
            +
                    elsif protocol_version = val[:proxy_protocol]
         
     | 
| 
      
 961 
     | 
    
         
            +
                      @options[:remote_address] = :proxy_protocol
         
     | 
| 
      
 962 
     | 
    
         
            +
                      protocol_version = protocol_version.downcase.to_sym
         
     | 
| 
      
 963 
     | 
    
         
            +
                      unless [:v1].include?(protocol_version)
         
     | 
| 
      
 964 
     | 
    
         
            +
                        raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
         
     | 
| 
      
 965 
     | 
    
         
            +
                      end
         
     | 
| 
      
 966 
     | 
    
         
            +
                      @options[:remote_address_proxy_protocol] = protocol_version
         
     | 
| 
       842 
967 
     | 
    
         
             
                    else
         
     | 
| 
       843 
968 
     | 
    
         
             
                      raise "Invalid value for set_remote_address - #{val.inspect}"
         
     | 
| 
       844 
969 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -864,23 +989,6 @@ module Puma 
     | 
|
| 
       864 
989 
     | 
    
         
             
                  @options[:fork_worker] = Integer(after_requests)
         
     | 
| 
       865 
990 
     | 
    
         
             
                end
         
     | 
| 
       866 
991 
     | 
    
         | 
| 
       867 
     | 
    
         
            -
                # When enabled, Puma will GC 4 times before forking workers.
         
     | 
| 
       868 
     | 
    
         
            -
                # If available (Ruby 2.7+), we will also call GC.compact.
         
     | 
| 
       869 
     | 
    
         
            -
                # Not recommended for non-MRI Rubies.
         
     | 
| 
       870 
     | 
    
         
            -
                #
         
     | 
| 
       871 
     | 
    
         
            -
                # Based on the work of Koichi Sasada and Aaron Patterson, this option may
         
     | 
| 
       872 
     | 
    
         
            -
                # decrease memory utilization of preload-enabled cluster-mode Pumas. It will
         
     | 
| 
       873 
     | 
    
         
            -
                # also increase time to boot and fork. See your logs for details on how much
         
     | 
| 
       874 
     | 
    
         
            -
                # time this adds to your boot process. For most apps, it will be less than one
         
     | 
| 
       875 
     | 
    
         
            -
                # second.
         
     | 
| 
       876 
     | 
    
         
            -
                #
         
     | 
| 
       877 
     | 
    
         
            -
                # @see Puma::Cluster#nakayoshi_gc
         
     | 
| 
       878 
     | 
    
         
            -
                # @version 5.0.0
         
     | 
| 
       879 
     | 
    
         
            -
                #
         
     | 
| 
       880 
     | 
    
         
            -
                def nakayoshi_fork(enabled=true)
         
     | 
| 
       881 
     | 
    
         
            -
                  @options[:nakayoshi_fork] = enabled
         
     | 
| 
       882 
     | 
    
         
            -
                end
         
     | 
| 
       883 
     | 
    
         
            -
             
     | 
| 
       884 
992 
     | 
    
         
             
                # The number of requests to attempt inline before sending a client back to
         
     | 
| 
       885 
993 
     | 
    
         
             
                # the reactor to be subject to normal ordering.
         
     | 
| 
       886 
994 
     | 
    
         
             
                #
         
     | 
| 
         @@ -910,5 +1018,36 @@ module Puma 
     | 
|
| 
       910 
1018 
     | 
    
         
             
                def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
         
     | 
| 
       911 
1019 
     | 
    
         
             
                  @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
         
     | 
| 
       912 
1020 
     | 
    
         
             
                end
         
     | 
| 
      
 1021 
     | 
    
         
            +
             
     | 
| 
      
 1022 
     | 
    
         
            +
                private
         
     | 
| 
      
 1023 
     | 
    
         
            +
             
     | 
| 
      
 1024 
     | 
    
         
            +
                # To avoid adding cert_pem and key_pem as URI params, we store them on the
         
     | 
| 
      
 1025 
     | 
    
         
            +
                # options[:store] from where Puma binder knows how to find and extract them.
         
     | 
| 
      
 1026 
     | 
    
         
            +
                def add_pem_values_to_options_store(opts)
         
     | 
| 
      
 1027 
     | 
    
         
            +
                  return if defined?(JRUBY_VERSION)
         
     | 
| 
      
 1028 
     | 
    
         
            +
             
     | 
| 
      
 1029 
     | 
    
         
            +
                  @options[:store] ||= []
         
     | 
| 
      
 1030 
     | 
    
         
            +
             
     | 
| 
      
 1031 
     | 
    
         
            +
                  # Store cert_pem and key_pem to options[:store] if present
         
     | 
| 
      
 1032 
     | 
    
         
            +
                  [:cert, :key].each do |v|
         
     | 
| 
      
 1033 
     | 
    
         
            +
                    opt_key = :"#{v}_pem"
         
     | 
| 
      
 1034 
     | 
    
         
            +
                    if opts[opt_key]
         
     | 
| 
      
 1035 
     | 
    
         
            +
                      index = @options[:store].length
         
     | 
| 
      
 1036 
     | 
    
         
            +
                      @options[:store] << opts[opt_key]
         
     | 
| 
      
 1037 
     | 
    
         
            +
                      opts[v] = "store:#{index}"
         
     | 
| 
      
 1038 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1039 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1040 
     | 
    
         
            +
                end
         
     | 
| 
      
 1041 
     | 
    
         
            +
             
     | 
| 
      
 1042 
     | 
    
         
            +
                def process_hook(options_key, key, block, meth)
         
     | 
| 
      
 1043 
     | 
    
         
            +
                  @options[options_key] ||= []
         
     | 
| 
      
 1044 
     | 
    
         
            +
                  if ON_WORKER_KEY.include? key.class
         
     | 
| 
      
 1045 
     | 
    
         
            +
                    @options[options_key] << [block, key.to_sym]
         
     | 
| 
      
 1046 
     | 
    
         
            +
                  elsif key.nil?
         
     | 
| 
      
 1047 
     | 
    
         
            +
                    @options[options_key] << block
         
     | 
| 
      
 1048 
     | 
    
         
            +
                  else
         
     | 
| 
      
 1049 
     | 
    
         
            +
                    raise "'#{method}' key must be String or Symbol"
         
     | 
| 
      
 1050 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1051 
     | 
    
         
            +
                end
         
     | 
| 
       913 
1052 
     | 
    
         
             
              end
         
     | 
| 
       914 
1053 
     | 
    
         
             
            end
         
     | 
    
        data/lib/puma/error_logger.rb
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'const'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            module Puma
         
     | 
| 
       6 
6 
     | 
    
         
             
              # The implementation of a detailed error logging.
         
     | 
| 
         @@ -13,6 +13,8 @@ module Puma 
     | 
|
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                REQUEST_FORMAT = %{"%s %s%s" - (%s)}
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
                LOG_QUEUE = Queue.new
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       16 
18 
     | 
    
         
             
                def initialize(ioerr)
         
     | 
| 
       17 
19 
     | 
    
         
             
                  @ioerr = ioerr
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
         @@ -31,7 +33,7 @@ module Puma 
     | 
|
| 
       31 
33 
     | 
    
         
             
                #   and before all remaining info.
         
     | 
| 
       32 
34 
     | 
    
         
             
                #
         
     | 
| 
       33 
35 
     | 
    
         
             
                def info(options={})
         
     | 
| 
       34 
     | 
    
         
            -
                   
     | 
| 
      
 36 
     | 
    
         
            +
                  internal_write title(options)
         
     | 
| 
       35 
37 
     | 
    
         
             
                end
         
     | 
| 
       36 
38 
     | 
    
         | 
| 
       37 
39 
     | 
    
         
             
                # Print occurred error details only if
         
     | 
| 
         @@ -53,7 +55,7 @@ module Puma 
     | 
|
| 
       53 
55 
     | 
    
         
             
                  string_block << request_dump(req) if request_parsed?(req)
         
     | 
| 
       54 
56 
     | 
    
         
             
                  string_block << error.backtrace if error
         
     | 
| 
       55 
57 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                   
     | 
| 
      
 58 
     | 
    
         
            +
                  internal_write string_block.join("\n")
         
     | 
| 
       57 
59 
     | 
    
         
             
                end
         
     | 
| 
       58 
60 
     | 
    
         | 
| 
       59 
61 
     | 
    
         
             
                def title(options={})
         
     | 
| 
         @@ -93,12 +95,18 @@ module Puma 
     | 
|
| 
       93 
95 
     | 
    
         
             
                  req && req.env[REQUEST_METHOD]
         
     | 
| 
       94 
96 
     | 
    
         
             
                end
         
     | 
| 
       95 
97 
     | 
    
         | 
| 
       96 
     | 
    
         
            -
                 
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
      
 98 
     | 
    
         
            +
                def internal_write(str)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  LOG_QUEUE << str
         
     | 
| 
      
 100 
     | 
    
         
            +
                  while (w_str = LOG_QUEUE.pop(true)) do
         
     | 
| 
      
 101 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 102 
     | 
    
         
            +
                      @ioerr.is_a?(IO) and @ioerr.wait_writable(1)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      @ioerr.write "#{w_str}\n"
         
     | 
| 
      
 104 
     | 
    
         
            +
                      @ioerr.flush unless @ioerr.sync
         
     | 
| 
      
 105 
     | 
    
         
            +
                    rescue Errno::EPIPE, Errno::EBADF, IOError
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                rescue ThreadError
         
     | 
| 
       102 
109 
     | 
    
         
             
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
                private :internal_write
         
     | 
| 
       103 
111 
     | 
    
         
             
              end
         
     | 
| 
       104 
112 
     | 
    
         
             
            end
         
     | 
    
        data/lib/puma/events.rb
    CHANGED
    
    | 
         @@ -1,52 +1,23 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require "puma/null_io"
         
     | 
| 
       4 
     | 
    
         
            -
            require 'puma/error_logger'
         
     | 
| 
       5 
     | 
    
         
            -
            require 'stringio'
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
3 
     | 
    
         
             
            module Puma
         
     | 
| 
       8 
     | 
    
         
            -
              # The default implement of an event sink object used by Server
         
     | 
| 
       9 
     | 
    
         
            -
              # for when certain kinds of events occur in the life of the server.
         
     | 
| 
       10 
     | 
    
         
            -
              #
         
     | 
| 
       11 
     | 
    
         
            -
              # The methods available are the events that the Server fires.
         
     | 
| 
       12 
     | 
    
         
            -
              #
         
     | 
| 
       13 
     | 
    
         
            -
              class Events
         
     | 
| 
       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 
     | 
    
         
            -
                # Create an Events object that prints to +stdout+ and +stderr+.
         
     | 
| 
       27 
     | 
    
         
            -
                #
         
     | 
| 
       28 
     | 
    
         
            -
                def initialize(stdout, stderr)
         
     | 
| 
       29 
     | 
    
         
            -
                  @formatter = DefaultFormatter.new
         
     | 
| 
       30 
     | 
    
         
            -
                  @stdout = stdout
         
     | 
| 
       31 
     | 
    
         
            -
                  @stderr = stderr
         
     | 
| 
       32 
4 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
              # This is an event sink used by `Puma::Server` to handle
         
     | 
| 
      
 6 
     | 
    
         
            +
              # lifecycle events such as :on_booted, :on_restart, and :on_stopped.
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Using `Puma::DSL` it is possible to register callback hooks
         
     | 
| 
      
 8 
     | 
    
         
            +
              # for each event type.
         
     | 
| 
      
 9 
     | 
    
         
            +
              class Events
         
     | 
| 
       35 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                def initialize
         
     | 
| 
       36 
12 
     | 
    
         
             
                  @hooks = Hash.new { |h,k| h[k] = [] }
         
     | 
| 
       37 
13 
     | 
    
         
             
                end
         
     | 
| 
       38 
14 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                attr_reader :stdout, :stderr
         
     | 
| 
       40 
     | 
    
         
            -
                attr_accessor :formatter
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
15 
     | 
    
         
             
                # Fire callbacks for the named hook
         
     | 
| 
       43 
     | 
    
         
            -
                #
         
     | 
| 
       44 
16 
     | 
    
         
             
                def fire(hook, *args)
         
     | 
| 
       45 
17 
     | 
    
         
             
                  @hooks[hook].each { |t| t.call(*args) }
         
     | 
| 
       46 
18 
     | 
    
         
             
                end
         
     | 
| 
       47 
19 
     | 
    
         | 
| 
       48 
20 
     | 
    
         
             
                # Register a callback for a given hook
         
     | 
| 
       49 
     | 
    
         
            -
                #
         
     | 
| 
       50 
21 
     | 
    
         
             
                def register(hook, obj=nil, &blk)
         
     | 
| 
       51 
22 
     | 
    
         
             
                  if obj and blk
         
     | 
| 
       52 
23 
     | 
    
         
             
                    raise "Specify either an object or a block, not both"
         
     | 
| 
         @@ -59,79 +30,6 @@ module Puma 
     | 
|
| 
       59 
30 
     | 
    
         
             
                  h
         
     | 
| 
       60 
31 
     | 
    
         
             
                end
         
     | 
| 
       61 
32 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                # Write +str+ to +@stdout+
         
     | 
| 
       63 
     | 
    
         
            -
                #
         
     | 
| 
       64 
     | 
    
         
            -
                def log(str)
         
     | 
| 
       65 
     | 
    
         
            -
                  @stdout.puts format(str) if @stdout.respond_to? :puts
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
                  @stdout.flush unless @stdout.sync
         
     | 
| 
       68 
     | 
    
         
            -
                rescue Errno::EPIPE
         
     | 
| 
       69 
     | 
    
         
            -
                end
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                def write(str)
         
     | 
| 
       72 
     | 
    
         
            -
                  @stdout.write format(str)
         
     | 
| 
       73 
     | 
    
         
            -
                end
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
                def debug(str)
         
     | 
| 
       76 
     | 
    
         
            -
                  log("% #{str}") if @debug
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                # Write +str+ to +@stderr+
         
     | 
| 
       80 
     | 
    
         
            -
                #
         
     | 
| 
       81 
     | 
    
         
            -
                def error(str)
         
     | 
| 
       82 
     | 
    
         
            -
                  @error_logger.info(text: format("ERROR: #{str}"))
         
     | 
| 
       83 
     | 
    
         
            -
                  exit 1
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                def format(str)
         
     | 
| 
       87 
     | 
    
         
            -
                  formatter.call(str)
         
     | 
| 
       88 
     | 
    
         
            -
                end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                # An HTTP connection error has occurred.
         
     | 
| 
       91 
     | 
    
         
            -
                # +error+ a connection exception, +req+ the request,
         
     | 
| 
       92 
     | 
    
         
            -
                # and +text+ additional info
         
     | 
| 
       93 
     | 
    
         
            -
                # @version 5.0.0
         
     | 
| 
       94 
     | 
    
         
            -
                #
         
     | 
| 
       95 
     | 
    
         
            -
                def connection_error(error, req, text="HTTP connection error")
         
     | 
| 
       96 
     | 
    
         
            -
                  @error_logger.info(error: error, req: req, text: text)
         
     | 
| 
       97 
     | 
    
         
            -
                end
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                # An HTTP parse error has occurred.
         
     | 
| 
       100 
     | 
    
         
            -
                # +error+ a parsing exception,
         
     | 
| 
       101 
     | 
    
         
            -
                # and +req+ the request.
         
     | 
| 
       102 
     | 
    
         
            -
                #
         
     | 
| 
       103 
     | 
    
         
            -
                def parse_error(error, req)
         
     | 
| 
       104 
     | 
    
         
            -
                  @error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
         
     | 
| 
       105 
     | 
    
         
            -
                end
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
                # An SSL error has occurred.
         
     | 
| 
       108 
     | 
    
         
            -
                # @param error <Puma::MiniSSL::SSLError>
         
     | 
| 
       109 
     | 
    
         
            -
                # @param ssl_socket <Puma::MiniSSL::Socket>
         
     | 
| 
       110 
     | 
    
         
            -
                #
         
     | 
| 
       111 
     | 
    
         
            -
                def ssl_error(error, ssl_socket)
         
     | 
| 
       112 
     | 
    
         
            -
                  peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
         
     | 
| 
       113 
     | 
    
         
            -
                  peercert = ssl_socket.peercert
         
     | 
| 
       114 
     | 
    
         
            -
                  subject = peercert ? peercert.subject : nil
         
     | 
| 
       115 
     | 
    
         
            -
                  @error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
         
     | 
| 
       116 
     | 
    
         
            -
                end
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                # An unknown error has occurred.
         
     | 
| 
       119 
     | 
    
         
            -
                # +error+ an exception object, +req+ the request,
         
     | 
| 
       120 
     | 
    
         
            -
                # and +text+ additional info
         
     | 
| 
       121 
     | 
    
         
            -
                #
         
     | 
| 
       122 
     | 
    
         
            -
                def unknown_error(error, req=nil, text="Unknown error")
         
     | 
| 
       123 
     | 
    
         
            -
                  @error_logger.info(error: error, req: req, text: text)
         
     | 
| 
       124 
     | 
    
         
            -
                end
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
                # Log occurred error debug dump.
         
     | 
| 
       127 
     | 
    
         
            -
                # +error+ an exception object, +req+ the request,
         
     | 
| 
       128 
     | 
    
         
            -
                # and +text+ additional info
         
     | 
| 
       129 
     | 
    
         
            -
                # @version 5.0.0
         
     | 
| 
       130 
     | 
    
         
            -
                #
         
     | 
| 
       131 
     | 
    
         
            -
                def debug_error(error, req=nil, text="")
         
     | 
| 
       132 
     | 
    
         
            -
                  @error_logger.debug(error: error, req: req, text: text)
         
     | 
| 
       133 
     | 
    
         
            -
                end
         
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
33 
     | 
    
         
             
                def on_booted(&block)
         
     | 
| 
       136 
34 
     | 
    
         
             
                  register(:on_booted, &block)
         
     | 
| 
       137 
35 
     | 
    
         
             
                end
         
     | 
| 
         @@ -155,23 +53,5 @@ module Puma 
     | 
|
| 
       155 
53 
     | 
    
         
             
                def fire_on_stopped!
         
     | 
| 
       156 
54 
     | 
    
         
             
                  fire(:on_stopped)
         
     | 
| 
       157 
55 
     | 
    
         
             
                end
         
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
                DEFAULT = new(STDOUT, STDERR)
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                # Returns an Events object which writes its status to 2 StringIO
         
     | 
| 
       162 
     | 
    
         
            -
                # objects.
         
     | 
| 
       163 
     | 
    
         
            -
                #
         
     | 
| 
       164 
     | 
    
         
            -
                def self.strings
         
     | 
| 
       165 
     | 
    
         
            -
                  Events.new StringIO.new, StringIO.new
         
     | 
| 
       166 
     | 
    
         
            -
                end
         
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
       168 
     | 
    
         
            -
                def self.stdio
         
     | 
| 
       169 
     | 
    
         
            -
                  Events.new $stdout, $stderr
         
     | 
| 
       170 
     | 
    
         
            -
                end
         
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
                def self.null
         
     | 
| 
       173 
     | 
    
         
            -
                  n = NullIO.new
         
     | 
| 
       174 
     | 
    
         
            -
                  Events.new n, n
         
     | 
| 
       175 
     | 
    
         
            -
                end
         
     | 
| 
       176 
56 
     | 
    
         
             
              end
         
     | 
| 
       177 
57 
     | 
    
         
             
            end
         
     | 
    
        data/lib/puma/io_buffer.rb
    CHANGED
    
    | 
         @@ -1,11 +1,36 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            require 'stringio'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
            module Puma
         
     | 
| 
       4 
     | 
    
         
            -
              class IOBuffer <  
     | 
| 
       5 
     | 
    
         
            -
                def  
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
      
 6 
     | 
    
         
            +
              class IOBuffer < StringIO
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 8 
     | 
    
         
            +
                  super.binmode
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def empty?
         
     | 
| 
      
 12 
     | 
    
         
            +
                  length.zero?
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def reset
         
     | 
| 
      
 16 
     | 
    
         
            +
                  truncate 0
         
     | 
| 
      
 17 
     | 
    
         
            +
                  rewind
         
     | 
| 
       7 
18 
     | 
    
         
             
                end
         
     | 
| 
       8 
19 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
      
 20 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 21 
     | 
    
         
            +
                  rewind
         
     | 
| 
      
 22 
     | 
    
         
            +
                  read
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                alias_method :clear, :reset
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                # before Ruby 2.5, `write` would only take one argument
         
     | 
| 
      
 28 
     | 
    
         
            +
                if RUBY_VERSION >= '2.5' && RUBY_ENGINE != 'truffleruby'
         
     | 
| 
      
 29 
     | 
    
         
            +
                  alias_method :append, :write
         
     | 
| 
      
 30 
     | 
    
         
            +
                else
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def append(*strs)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    strs.each { |str| write str }
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
       10 
35 
     | 
    
         
             
              end
         
     | 
| 
       11 
36 
     | 
    
         
             
            end
         
     | 
    
        data/lib/puma/jruby_restart.rb
    CHANGED
    
    
| 
         @@ -17,7 +17,7 @@ module Puma 
     | 
|
| 
       17 
17 
     | 
    
         
             
              # be particularly full-featured or fast. It just has to handle the few places
         
     | 
| 
       18 
18 
     | 
    
         
             
              # where Puma relies on JSON serialization internally.
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
              module  
     | 
| 
      
 20 
     | 
    
         
            +
              module JSONSerialization
         
     | 
| 
       21 
21 
     | 
    
         
             
                QUOTE = /"/
         
     | 
| 
       22 
22 
     | 
    
         
             
                BACKSLASH = /\\/
         
     | 
| 
       23 
23 
     | 
    
         
             
                CONTROL_CHAR_TO_ESCAPE = /[\x00-\x1F]/ # As required by ECMA-404
         
     |