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.

Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +284 -11
  3. data/LICENSE +0 -0
  4. data/README.md +61 -16
  5. data/bin/puma-wild +1 -1
  6. data/docs/architecture.md +49 -16
  7. data/docs/compile_options.md +38 -2
  8. data/docs/deployment.md +53 -67
  9. data/docs/fork_worker.md +1 -3
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +0 -0
  17. data/docs/nginx.md +0 -0
  18. data/docs/plugins.md +15 -15
  19. data/docs/rails_dev_mode.md +2 -3
  20. data/docs/restart.md +6 -6
  21. data/docs/signals.md +11 -10
  22. data/docs/stats.md +8 -8
  23. data/docs/systemd.md +64 -67
  24. data/docs/testing_benchmarks_local_files.md +150 -0
  25. data/docs/testing_test_rackup_ci_files.md +36 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +44 -13
  29. data/ext/puma_http11/http11_parser.c +24 -11
  30. data/ext/puma_http11/http11_parser.h +1 -1
  31. data/ext/puma_http11/http11_parser.java.rl +2 -2
  32. data/ext/puma_http11/http11_parser.rl +2 -2
  33. data/ext/puma_http11/http11_parser_common.rl +3 -3
  34. data/ext/puma_http11/mini_ssl.c +122 -23
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +50 -48
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +188 -102
  39. data/ext/puma_http11/puma_http11.c +18 -10
  40. data/lib/puma/app/status.rb +9 -6
  41. data/lib/puma/binder.rb +81 -42
  42. data/lib/puma/cli.rb +23 -19
  43. data/lib/puma/client.rb +124 -30
  44. data/lib/puma/cluster/worker.rb +21 -29
  45. data/lib/puma/cluster/worker_handle.rb +8 -1
  46. data/lib/puma/cluster.rb +57 -48
  47. data/lib/puma/commonlogger.rb +0 -0
  48. data/lib/puma/configuration.rb +74 -55
  49. data/lib/puma/const.rb +21 -24
  50. data/lib/puma/control_cli.rb +22 -19
  51. data/lib/puma/detect.rb +10 -2
  52. data/lib/puma/dsl.rb +196 -57
  53. data/lib/puma/error_logger.rb +17 -9
  54. data/lib/puma/events.rb +6 -126
  55. data/lib/puma/io_buffer.rb +29 -4
  56. data/lib/puma/jruby_restart.rb +2 -1
  57. data/lib/puma/{json.rb → json_serialization.rb} +1 -1
  58. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  59. data/lib/puma/launcher.rb +108 -154
  60. data/lib/puma/log_writer.rb +137 -0
  61. data/lib/puma/minissl/context_builder.rb +29 -16
  62. data/lib/puma/minissl.rb +115 -38
  63. data/lib/puma/null_io.rb +5 -0
  64. data/lib/puma/plugin/tmp_restart.rb +1 -1
  65. data/lib/puma/plugin.rb +2 -2
  66. data/lib/puma/rack/builder.rb +5 -5
  67. data/lib/puma/rack/urlmap.rb +0 -0
  68. data/lib/puma/rack_default.rb +1 -1
  69. data/lib/puma/reactor.rb +3 -3
  70. data/lib/puma/request.rb +293 -153
  71. data/lib/puma/runner.rb +63 -28
  72. data/lib/puma/server.rb +83 -88
  73. data/lib/puma/single.rb +10 -10
  74. data/lib/puma/state_file.rb +39 -7
  75. data/lib/puma/systemd.rb +3 -2
  76. data/lib/puma/thread_pool.rb +22 -17
  77. data/lib/puma/util.rb +20 -15
  78. data/lib/puma.rb +12 -9
  79. data/lib/rack/handler/puma.rb +9 -9
  80. data/tools/Dockerfile +1 -1
  81. data/tools/trickletest.rb +0 -0
  82. metadata +13 -9
  83. data/lib/puma/queue_close.rb +0 -26
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'thread'
4
4
 
5
+ require_relative 'io_buffer'
6
+
5
7
  module Puma
6
8
  # Internal Docs for A simple thread pool management object.
7
9
  #
@@ -29,7 +31,7 @@ module Puma
29
31
  # The block passed is the work that will be performed in each
30
32
  # thread.
31
33
  #
32
- def initialize(min, max, *extra, &block)
34
+ def initialize(name, options = {}, &block)
33
35
  @not_empty = ConditionVariable.new
34
36
  @not_full = ConditionVariable.new
35
37
  @mutex = Mutex.new
@@ -39,10 +41,15 @@ module Puma
39
41
  @spawned = 0
40
42
  @waiting = 0
41
43
 
42
- @min = Integer(min)
43
- @max = Integer(max)
44
+ @name = name
45
+ @min = Integer(options[:min_threads])
46
+ @max = Integer(options[:max_threads])
44
47
  @block = block
45
- @extra = extra
48
+ @extra = [::Puma::IOBuffer]
49
+ @out_of_band = options[:out_of_band]
50
+ @clean_thread_locals = options[:clean_thread_locals]
51
+ @reaping_time = options[:reaping_time]
52
+ @auto_trim_time = options[:auto_trim_time]
46
53
 
47
54
  @shutdown = false
48
55
 
@@ -61,17 +68,14 @@ module Puma
61
68
  end
62
69
  end
63
70
 
64
- @clean_thread_locals = false
65
71
  @force_shutdown = false
66
72
  @shutdown_mutex = Mutex.new
67
73
  end
68
74
 
69
75
  attr_reader :spawned, :trim_requested, :waiting
70
- attr_accessor :clean_thread_locals
71
- attr_accessor :out_of_band_hook # @version 5.0.0
72
76
 
73
77
  def self.clean_thread_locals
74
- Thread.current.keys.each do |key| # rubocop: disable Performance/HashEachMethods
78
+ Thread.current.keys.each do |key| # rubocop: disable Style/HashEachMethods
75
79
  Thread.current[key] = nil unless key == :__recursive_key__
76
80
  end
77
81
  end
@@ -101,7 +105,7 @@ module Puma
101
105
  @spawned += 1
102
106
 
103
107
  th = Thread.new(@spawned) do |spawned|
104
- Puma.set_thread_name 'threadpool %03i' % spawned
108
+ Puma.set_thread_name '%s tp %03i' % [@name, spawned]
105
109
  todo = @todo
106
110
  block = @block
107
111
  mutex = @mutex
@@ -119,6 +123,7 @@ module Puma
119
123
  @trim_requested -= 1
120
124
  @spawned -= 1
121
125
  @workers.delete th
126
+ not_full.signal
122
127
  Thread.exit
123
128
  end
124
129
 
@@ -158,12 +163,12 @@ module Puma
158
163
 
159
164
  # @version 5.0.0
160
165
  def trigger_out_of_band_hook
161
- return false unless out_of_band_hook && out_of_band_hook.any?
166
+ return false unless @out_of_band&.any?
162
167
 
163
168
  # we execute on idle hook when all threads are free
164
169
  return false unless @spawned == @waiting
165
170
 
166
- out_of_band_hook.each(&:call)
171
+ @out_of_band.each(&:call)
167
172
  true
168
173
  rescue Exception => e
169
174
  STDERR.puts "Exception calling out_of_band_hook: #{e.message} (#{e.class})"
@@ -317,13 +322,13 @@ module Puma
317
322
  end
318
323
  end
319
324
 
320
- def auto_trim!(timeout=30)
321
- @auto_trim = Automaton.new(self, timeout, "threadpool trimmer", :trim)
325
+ def auto_trim!(timeout=@auto_trim_time)
326
+ @auto_trim = Automaton.new(self, timeout, "#{@name} threadpool trimmer", :trim)
322
327
  @auto_trim.start!
323
328
  end
324
329
 
325
- def auto_reap!(timeout=5)
326
- @reaper = Automaton.new(self, timeout, "threadpool reaper", :reap)
330
+ def auto_reap!(timeout=@reaping_time)
331
+ @reaper = Automaton.new(self, timeout, "#{@name} threadpool reaper", :reap)
327
332
  @reaper.start!
328
333
  end
329
334
 
@@ -352,8 +357,8 @@ module Puma
352
357
  @not_empty.broadcast
353
358
  @not_full.broadcast
354
359
 
355
- @auto_trim.stop if @auto_trim
356
- @reaper.stop if @reaper
360
+ @auto_trim&.stop
361
+ @reaper&.stop
357
362
  # dup workers so that we join them all safely
358
363
  @workers.dup
359
364
  end
data/lib/puma/util.rb CHANGED
@@ -10,29 +10,34 @@ module Puma
10
10
  IO.pipe
11
11
  end
12
12
 
13
- # Unescapes a URI escaped string with +encoding+. +encoding+ will be the
14
- # target encoding of the string returned, and it defaults to UTF-8
13
+ # An instance method on Thread has been provided to address https://bugs.ruby-lang.org/issues/13632,
14
+ # which currently effects some older versions of Ruby: 2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1
15
+ # Additional context: https://github.com/puma/puma/pull/1345
16
+ def purge_interrupt_queue
17
+ Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
18
+ end
19
+
20
+ # Escapes and unescapes a URI escaped string with
21
+ # +encoding+. +encoding+ will be the target encoding of the string
22
+ # returned, and it defaults to UTF-8
15
23
  if defined?(::Encoding)
24
+ def escape(s, encoding = Encoding::UTF_8)
25
+ URI.encode_www_form_component(s, encoding)
26
+ end
27
+
16
28
  def unescape(s, encoding = Encoding::UTF_8)
17
29
  URI.decode_www_form_component(s, encoding)
18
30
  end
19
31
  else
20
- def unescape(s, encoding = nil)
21
- URI.decode_www_form_component(s, encoding)
32
+ def escape(s, encoding = nil)
33
+ URI.encode_www_form_component(s, encoding)
22
34
  end
23
- end
24
- module_function :unescape
25
35
 
26
- # @version 5.0.0
27
- def nakayoshi_gc(events)
28
- events.log "! Promoting existing objects to old generation..."
29
- 4.times { GC.start(full_mark: false) }
30
- if GC.respond_to?(:compact)
31
- events.log "! Compacting..."
32
- GC.compact
36
+ def unescape(s, encoding = nil)
37
+ URI.decode_www_form_component(s, encoding)
33
38
  end
34
- events.log "! Friendly fork preparation complete."
35
39
  end
40
+ module_function :unescape, :escape
36
41
 
37
42
  DEFAULT_SEP = /[&;] */n
38
43
 
@@ -61,7 +66,7 @@ module Puma
61
66
  end
62
67
  end
63
68
 
64
- return params
69
+ params
65
70
  end
66
71
 
67
72
  # A case-insensitive Hash that preserves the original case of a
data/lib/puma.rb CHANGED
@@ -10,14 +10,19 @@ require 'stringio'
10
10
 
11
11
  require 'thread'
12
12
 
13
+ # use require, see https://github.com/puma/puma/pull/2381
13
14
  require 'puma/puma_http11'
14
- require 'puma/detect'
15
- require 'puma/json'
15
+
16
+ require_relative 'puma/detect'
17
+ require_relative 'puma/json_serialization'
16
18
 
17
19
  module Puma
18
- autoload :Const, 'puma/const'
19
- autoload :Server, 'puma/server'
20
- autoload :Launcher, 'puma/launcher'
20
+ # when Puma is loaded via `Puma::CLI`, all files are loaded via
21
+ # `require_relative`. The below are for non-standard loading
22
+ autoload :Const, "#{__dir__}/puma/const"
23
+ autoload :Server, "#{__dir__}/puma/server"
24
+ autoload :Launcher, "#{__dir__}/puma/launcher"
25
+ autoload :LogWriter, "#{__dir__}/puma/log_writer"
21
26
 
22
27
  # at present, MiniSSL::Engine is only defined in extension code (puma_http11),
23
28
  # not in minissl.rb
@@ -26,7 +31,7 @@ module Puma
26
31
  HAS_UNIX_SOCKET = Object.const_defined? :UNIXSocket
27
32
 
28
33
  if HAS_SSL
29
- require 'puma/minissl'
34
+ require_relative 'puma/minissl'
30
35
  else
31
36
  module MiniSSL
32
37
  # this class is defined so that it exists when Puma is compiled
@@ -60,7 +65,7 @@ module Puma
60
65
 
61
66
  # @!attribute [rw] stats_object
62
67
  def self.stats
63
- Puma::JSON.generate @get_stats.stats
68
+ Puma::JSONSerialization.generate @get_stats.stats
64
69
  end
65
70
 
66
71
  # @!attribute [r] stats_hash
@@ -69,9 +74,7 @@ module Puma
69
74
  @get_stats.stats
70
75
  end
71
76
 
72
- # Thread name is new in Ruby 2.3
73
77
  def self.set_thread_name(name)
74
- return unless Thread.current.respond_to?(:name=)
75
78
  Thread.current.name = "puma #{name}"
76
79
  end
77
80
  end
@@ -11,10 +11,10 @@ module Rack
11
11
  }
12
12
 
13
13
  def self.config(app, options = {})
14
- require 'puma'
15
- require 'puma/configuration'
16
- require 'puma/events'
17
- require 'puma/launcher'
14
+ require_relative '../../puma'
15
+ require_relative '../../puma/configuration'
16
+ require_relative '../../puma/log_writer'
17
+ require_relative '../../puma/launcher'
18
18
 
19
19
  default_options = DEFAULT_OPTIONS.dup
20
20
 
@@ -63,9 +63,9 @@ module Rack
63
63
  def self.run(app, **options)
64
64
  conf = self.config(app, options)
65
65
 
66
- events = options.delete(:Silent) ? ::Puma::Events.strings : ::Puma::Events.stdio
66
+ log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
67
67
 
68
- launcher = ::Puma::Launcher.new(conf, :events => events)
68
+ launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
69
69
 
70
70
  yield launcher if block_given?
71
71
  begin
@@ -93,16 +93,16 @@ module Rack
93
93
  config.bind "unix://#{host}"
94
94
  elsif host && host =~ /^ssl:\/\//
95
95
  uri = URI.parse(host)
96
- uri.port ||= port || ::Puma::Configuration::DefaultTCPPort
96
+ uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
97
97
  config.bind uri.to_s
98
98
  else
99
99
 
100
100
  if host
101
- port ||= ::Puma::Configuration::DefaultTCPPort
101
+ port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
102
102
  end
103
103
 
104
104
  if port
105
- host ||= ::Puma::Configuration::DefaultTCPHost
105
+ host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
106
106
  config.port port, host
107
107
  end
108
108
  end
data/tools/Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
1
  # Use this Dockerfile to create minimal reproductions of issues
2
2
 
3
- FROM ruby:2.6
3
+ FROM ruby:3.1
4
4
 
5
5
  # throw errors if Gemfile has been modified since Gemfile.lock
6
6
  RUN bundle config --global frozen 1
data/tools/trickletest.rb CHANGED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.2
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-21 00:00:00.000000000 Z
11
+ date: 1980-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -24,9 +24,9 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
- description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
27
+ description: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server
28
28
  for Ruby/Rack applications. Puma is intended for use in both development and production
29
- environments. It's great for highly concurrent Ruby implementations such as Rubinius
29
+ environments. It's great for highly parallel Ruby implementations such as Rubinius
30
30
  and JRuby as well as as providing process worker support to support CRuby well.
31
31
  email:
32
32
  - evan@phx.io
@@ -62,6 +62,8 @@ files:
62
62
  - docs/signals.md
63
63
  - docs/stats.md
64
64
  - docs/systemd.md
65
+ - docs/testing_benchmarks_local_files.md
66
+ - docs/testing_test_rackup_ci_files.md
65
67
  - ext/puma_http11/PumaHttp11Service.java
66
68
  - ext/puma_http11/ext_help.h
67
69
  - ext/puma_http11/extconf.rb
@@ -94,14 +96,15 @@ files:
94
96
  - lib/puma/events.rb
95
97
  - lib/puma/io_buffer.rb
96
98
  - lib/puma/jruby_restart.rb
97
- - lib/puma/json.rb
99
+ - lib/puma/json_serialization.rb
98
100
  - lib/puma/launcher.rb
101
+ - lib/puma/launcher/bundle_pruner.rb
102
+ - lib/puma/log_writer.rb
99
103
  - lib/puma/minissl.rb
100
104
  - lib/puma/minissl/context_builder.rb
101
105
  - lib/puma/null_io.rb
102
106
  - lib/puma/plugin.rb
103
107
  - lib/puma/plugin/tmp_restart.rb
104
- - lib/puma/queue_close.rb
105
108
  - lib/puma/rack/builder.rb
106
109
  - lib/puma/rack/urlmap.rb
107
110
  - lib/puma/rack_default.rb
@@ -125,6 +128,7 @@ metadata:
125
128
  changelog_uri: https://github.com/puma/puma/blob/master/History.md
126
129
  homepage_uri: https://puma.io
127
130
  source_code_uri: https://github.com/puma/puma
131
+ rubygems_mfa_required: 'true'
128
132
  post_install_message:
129
133
  rdoc_options: []
130
134
  require_paths:
@@ -133,16 +137,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
137
  requirements:
134
138
  - - ">="
135
139
  - !ruby/object:Gem::Version
136
- version: '2.2'
140
+ version: '2.4'
137
141
  required_rubygems_version: !ruby/object:Gem::Requirement
138
142
  requirements:
139
143
  - - ">="
140
144
  - !ruby/object:Gem::Version
141
145
  version: '0'
142
146
  requirements: []
143
- rubygems_version: 3.2.3
147
+ rubygems_version: 3.2.26
144
148
  signing_key:
145
149
  specification_version: 4
146
- summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
150
+ summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for
147
151
  Ruby/Rack applications
148
152
  test_files: []
@@ -1,26 +0,0 @@
1
- class ClosedQueueError < StandardError; end
2
- module Puma
3
-
4
- # Queue#close was added in Ruby 2.3.
5
- # Add a simple implementation for earlier Ruby versions.
6
- #
7
- module QueueClose
8
- def close
9
- num_waiting.times {push nil}
10
- @closed = true
11
- end
12
- def closed?
13
- @closed ||= false
14
- end
15
- def push(object)
16
- raise ClosedQueueError if closed?
17
- super
18
- end
19
- alias << push
20
- def pop(non_block=false)
21
- return nil if !non_block && closed? && empty?
22
- super
23
- end
24
- end
25
- ::Queue.prepend QueueClose
26
- end