puma 3.11.4 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1717 -432
  3. data/LICENSE +23 -20
  4. data/README.md +190 -64
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +59 -21
  7. data/docs/compile_options.md +55 -0
  8. data/docs/deployment.md +69 -58
  9. data/docs/fork_worker.md +31 -0
  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 +9 -0
  14. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  15. data/{tools → docs}/jungle/rc.d/puma +2 -2
  16. data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
  17. data/docs/kubernetes.md +66 -0
  18. data/docs/nginx.md +2 -2
  19. data/docs/plugins.md +22 -12
  20. data/docs/rails_dev_mode.md +28 -0
  21. data/docs/restart.md +47 -22
  22. data/docs/signals.md +13 -11
  23. data/docs/stats.md +142 -0
  24. data/docs/systemd.md +95 -120
  25. data/docs/testing_benchmarks_local_files.md +150 -0
  26. data/docs/testing_test_rackup_ci_files.md +36 -0
  27. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  28. data/ext/puma_http11/ext_help.h +1 -1
  29. data/ext/puma_http11/extconf.rb +61 -3
  30. data/ext/puma_http11/http11_parser.c +106 -118
  31. data/ext/puma_http11/http11_parser.h +2 -2
  32. data/ext/puma_http11/http11_parser.java.rl +22 -38
  33. data/ext/puma_http11/http11_parser.rl +6 -4
  34. data/ext/puma_http11/http11_parser_common.rl +6 -6
  35. data/ext/puma_http11/mini_ssl.c +376 -93
  36. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  37. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  38. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
  39. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +250 -88
  40. data/ext/puma_http11/puma_http11.c +49 -57
  41. data/lib/puma/app/status.rb +71 -49
  42. data/lib/puma/binder.rb +243 -148
  43. data/lib/puma/cli.rb +50 -36
  44. data/lib/puma/client.rb +373 -233
  45. data/lib/puma/cluster/worker.rb +175 -0
  46. data/lib/puma/cluster/worker_handle.rb +97 -0
  47. data/lib/puma/cluster.rb +268 -235
  48. data/lib/puma/commonlogger.rb +4 -2
  49. data/lib/puma/configuration.rb +116 -88
  50. data/lib/puma/const.rb +49 -30
  51. data/lib/puma/control_cli.rb +123 -76
  52. data/lib/puma/detect.rb +33 -2
  53. data/lib/puma/dsl.rb +685 -135
  54. data/lib/puma/error_logger.rb +112 -0
  55. data/lib/puma/events.rb +17 -111
  56. data/lib/puma/io_buffer.rb +44 -5
  57. data/lib/puma/jruby_restart.rb +4 -59
  58. data/lib/puma/json_serialization.rb +96 -0
  59. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  60. data/lib/puma/launcher.rb +196 -130
  61. data/lib/puma/log_writer.rb +137 -0
  62. data/lib/puma/minissl/context_builder.rb +92 -0
  63. data/lib/puma/minissl.rb +249 -69
  64. data/lib/puma/null_io.rb +20 -1
  65. data/lib/puma/plugin/tmp_restart.rb +3 -1
  66. data/lib/puma/plugin.rb +9 -13
  67. data/lib/puma/rack/builder.rb +8 -9
  68. data/lib/puma/rack/urlmap.rb +2 -0
  69. data/lib/puma/rack_default.rb +3 -1
  70. data/lib/puma/reactor.rb +90 -187
  71. data/lib/puma/request.rb +644 -0
  72. data/lib/puma/runner.rb +94 -71
  73. data/lib/puma/server.rb +337 -715
  74. data/lib/puma/single.rb +27 -72
  75. data/lib/puma/state_file.rb +46 -7
  76. data/lib/puma/systemd.rb +47 -0
  77. data/lib/puma/thread_pool.rb +184 -93
  78. data/lib/puma/util.rb +23 -10
  79. data/lib/puma.rb +60 -3
  80. data/lib/rack/handler/puma.rb +17 -15
  81. data/tools/Dockerfile +16 -0
  82. data/tools/trickletest.rb +0 -1
  83. metadata +53 -33
  84. data/ext/puma_http11/io_buffer.c +0 -155
  85. data/lib/puma/accept_nonblock.rb +0 -23
  86. data/lib/puma/compat.rb +0 -14
  87. data/lib/puma/convenient.rb +0 -23
  88. data/lib/puma/daemon_ext.rb +0 -31
  89. data/lib/puma/delegation.rb +0 -11
  90. data/lib/puma/java_io_buffer.rb +0 -45
  91. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  92. data/lib/puma/tcp_logger.rb +0 -39
  93. data/tools/jungle/README.md +0 -19
  94. data/tools/jungle/init.d/README.md +0 -61
  95. data/tools/jungle/init.d/puma +0 -421
  96. data/tools/jungle/init.d/run-puma +0 -18
  97. data/tools/jungle/upstart/README.md +0 -61
  98. data/tools/jungle/upstart/puma-manager.conf +0 -31
  99. data/tools/jungle/upstart/puma.conf +0 -69
data/lib/puma/runner.rb CHANGED
@@ -1,76 +1,92 @@
1
- require 'puma/server'
2
- require 'puma/const'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'server'
4
+ require_relative 'const'
3
5
 
4
6
  module Puma
7
+ # Generic class that is used by `Puma::Cluster` and `Puma::Single` to
8
+ # serve requests. This class spawns a new instance of `Puma::Server` via
9
+ # a call to `start_server`.
5
10
  class Runner
6
- def initialize(cli, events)
7
- @launcher = cli
8
- @events = events
9
- @options = cli.options
11
+ def initialize(launcher)
12
+ @launcher = launcher
13
+ @log_writer = launcher.log_writer
14
+ @events = launcher.events
15
+ @config = launcher.config
16
+ @options = launcher.options
10
17
  @app = nil
11
18
  @control = nil
19
+ @started_at = Time.now
20
+ @wakeup = nil
12
21
  end
13
22
 
14
- def daemon?
15
- @options[:daemon]
23
+ # Returns the hash of configuration options.
24
+ # @return [Puma::UserFileDefaultOptions]
25
+ attr_reader :options
26
+
27
+ def wakeup!
28
+ return unless @wakeup
29
+
30
+ @wakeup.write "!" unless @wakeup.closed?
31
+
32
+ rescue SystemCallError, IOError
33
+ Puma::Util.purge_interrupt_queue
16
34
  end
17
35
 
18
36
  def development?
19
37
  @options[:environment] == "development"
20
38
  end
21
39
 
40
+ def test?
41
+ @options[:environment] == "test"
42
+ end
43
+
22
44
  def log(str)
23
- @events.log str
45
+ @log_writer.log str
24
46
  end
25
47
 
26
- def before_restart
27
- @control.stop(true) if @control
48
+ # @version 5.0.0
49
+ def stop_control
50
+ @control&.stop true
28
51
  end
29
52
 
30
53
  def error(str)
31
- @events.error str
54
+ @log_writer.error str
32
55
  end
33
56
 
34
57
  def debug(str)
35
- @events.log "- #{str}" if @options[:debug]
58
+ @log_writer.log "- #{str}" if @options[:debug]
36
59
  end
37
60
 
38
61
  def start_control
39
62
  str = @options[:control_url]
40
63
  return unless str
41
64
 
42
- require 'puma/app/status'
43
-
44
- uri = URI.parse str
45
-
46
- app = Puma::App::Status.new @launcher
65
+ require_relative 'app/status'
47
66
 
48
67
  if token = @options[:control_auth_token]
49
- app.auth_token = token unless token.empty? or token == :none
68
+ token = nil if token.empty? || token == 'none'
50
69
  end
51
70
 
52
- control = Puma::Server.new app, @launcher.events
53
- control.min_threads = 0
54
- control.max_threads = 1
71
+ app = Puma::App::Status.new @launcher, token
55
72
 
56
- case uri.scheme
57
- when "tcp"
58
- log "* Starting control server on #{str}"
59
- control.add_tcp_listener uri.host, uri.port
60
- when "unix"
61
- log "* Starting control server on #{str}"
62
- path = "#{uri.host}#{uri.path}"
63
- mask = @options[:control_url_umask]
73
+ # A Reactor is not created aand nio4r is not loaded when 'queue_requests: false'
74
+ # Use `nil` for events, no hooks in control server
75
+ control = Puma::Server.new app, nil,
76
+ { min_threads: 0, max_threads: 1, queue_requests: false, log_writer: @log_writer }
64
77
 
65
- control.add_unix_listener path, mask
66
- else
67
- error "Invalid control URI: #{str}"
68
- end
78
+ control.binder.parse [str], nil, 'Starting control server'
69
79
 
70
- control.run
80
+ control.run thread_name: 'ctl'
71
81
  @control = control
72
82
  end
73
83
 
84
+ # @version 5.0.0
85
+ def close_control_listeners
86
+ @control.binder.close_listeners if @control
87
+ end
88
+
89
+ # @!attribute [r] ruby_engine
74
90
  def ruby_engine
75
91
  if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
76
92
  "ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
@@ -86,14 +102,18 @@ module Puma
86
102
  def output_header(mode)
87
103
  min_t = @options[:min_threads]
88
104
  max_t = @options[:max_threads]
105
+ environment = @options[:environment]
89
106
 
90
107
  log "Puma starting in #{mode} mode..."
91
- log "* Version #{Puma::Const::PUMA_VERSION} (#{ruby_engine}), codename: #{Puma::Const::CODE_NAME}"
92
- log "* Min threads: #{min_t}, max threads: #{max_t}"
93
- log "* Environment: #{ENV['RACK_ENV']}"
108
+ log "* Puma version: #{Puma::Const::PUMA_VERSION} (#{ruby_engine}) (\"#{Puma::Const::CODE_NAME}\")"
109
+ log "* Min threads: #{min_t}"
110
+ log "* Max threads: #{max_t}"
111
+ log "* Environment: #{environment}"
94
112
 
95
- if @options[:mode] == :tcp
96
- log "* Mode: Lopez Express (tcp)"
113
+ if mode == "cluster"
114
+ log "* Master PID: #{Process.pid}"
115
+ else
116
+ log "* PID: #{Process.pid}"
97
117
  end
98
118
  end
99
119
 
@@ -107,69 +127,72 @@ module Puma
107
127
  append = @options[:redirect_append]
108
128
 
109
129
  if stdout
110
- unless Dir.exist?(File.dirname(stdout))
111
- raise "Cannot redirect STDOUT to #{stdout}"
112
- end
130
+ ensure_output_directory_exists(stdout, 'STDOUT')
113
131
 
114
132
  STDOUT.reopen stdout, (append ? "a" : "w")
115
- STDOUT.sync = true
116
133
  STDOUT.puts "=== puma startup: #{Time.now} ==="
134
+ STDOUT.flush unless STDOUT.sync
117
135
  end
118
136
 
119
137
  if stderr
120
- unless Dir.exist?(File.dirname(stderr))
121
- raise "Cannot redirect STDERR to #{stderr}"
122
- end
138
+ ensure_output_directory_exists(stderr, 'STDERR')
123
139
 
124
140
  STDERR.reopen stderr, (append ? "a" : "w")
125
- STDERR.sync = true
126
141
  STDERR.puts "=== puma startup: #{Time.now} ==="
142
+ STDERR.flush unless STDERR.sync
143
+ end
144
+
145
+ if @options[:mutate_stdout_and_stderr_to_sync_on_write]
146
+ STDOUT.sync = true
147
+ STDERR.sync = true
127
148
  end
128
149
  end
129
150
 
130
151
  def load_and_bind
131
- unless @launcher.config.app_configured?
152
+ unless @config.app_configured?
132
153
  error "No application configured, nothing to run"
133
154
  exit 1
134
155
  end
135
156
 
136
- # Load the app before we daemonize.
137
157
  begin
138
- @app = @launcher.config.app
158
+ @app = @config.app
139
159
  rescue Exception => e
140
160
  log "! Unable to load application: #{e.class}: #{e.message}"
141
161
  raise e
142
162
  end
143
163
 
144
- @launcher.binder.parse @options[:binds], self
164
+ @launcher.binder.parse @options[:binds]
145
165
  end
146
166
 
167
+ # @!attribute [r] app
147
168
  def app
148
- @app ||= @launcher.config.app
169
+ @app ||= @config.app
149
170
  end
150
171
 
151
172
  def start_server
152
- min_t = @options[:min_threads]
153
- max_t = @options[:max_threads]
154
-
155
- server = Puma::Server.new app, @launcher.events, @options
156
- server.min_threads = min_t
157
- server.max_threads = max_t
158
- server.inherit_binder @launcher.binder
159
-
160
- if @options[:mode] == :tcp
161
- server.tcp_mode!
162
- end
163
-
164
- if @options[:early_hints]
165
- server.early_hints = true
166
- end
173
+ server = Puma::Server.new(app, @events, @options)
174
+ server.inherit_binder(@launcher.binder)
175
+ server
176
+ end
167
177
 
168
- unless development?
169
- server.leak_stack_on_error = false
178
+ private
179
+ def ensure_output_directory_exists(path, io_name)
180
+ unless Dir.exist?(File.dirname(path))
181
+ raise "Cannot redirect #{io_name} to #{path}"
170
182
  end
183
+ end
171
184
 
172
- server
185
+ def stats
186
+ {
187
+ versions: {
188
+ puma: Puma::Const::PUMA_VERSION,
189
+ ruby: {
190
+ engine: RUBY_ENGINE,
191
+ version: RUBY_VERSION,
192
+ patchlevel: RUBY_PATCHLEVEL
193
+ }
194
+ }
195
+ }
173
196
  end
174
197
  end
175
198
  end