puma 4.3.1 → 5.0.0
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.
- checksums.yaml +4 -4
- data/History.md +94 -3
- data/LICENSE +23 -20
- data/README.md +26 -13
- data/docs/architecture.md +3 -3
- data/docs/deployment.md +9 -3
- data/docs/fork_worker.md +31 -0
- data/docs/jungle/README.md +13 -0
- data/{tools → docs}/jungle/rc.d/README.md +0 -0
- data/{tools → docs}/jungle/rc.d/puma +0 -0
- data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/{tools → docs}/jungle/upstart/README.md +0 -0
- data/{tools → docs}/jungle/upstart/puma-manager.conf +0 -0
- data/{tools → docs}/jungle/upstart/puma.conf +0 -0
- data/docs/signals.md +7 -6
- data/docs/systemd.md +1 -63
- data/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/extconf.rb +4 -3
- data/ext/puma_http11/http11_parser.c +3 -1
- data/ext/puma_http11/http11_parser.rl +3 -1
- data/ext/puma_http11/mini_ssl.c +15 -2
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +77 -18
- data/ext/puma_http11/puma_http11.c +7 -38
- data/lib/puma.rb +17 -0
- data/lib/puma/app/status.rb +18 -3
- data/lib/puma/binder.rb +88 -68
- data/lib/puma/cli.rb +7 -15
- data/lib/puma/client.rb +67 -14
- data/lib/puma/cluster.rb +191 -74
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +31 -42
- data/lib/puma/const.rb +4 -3
- data/lib/puma/control_cli.rb +29 -17
- data/lib/puma/detect.rb +17 -0
- data/lib/puma/dsl.rb +144 -70
- data/lib/puma/error_logger.rb +97 -0
- data/lib/puma/events.rb +35 -31
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/launcher.rb +49 -31
- data/lib/puma/minissl.rb +60 -18
- data/lib/puma/minissl/context_builder.rb +0 -3
- data/lib/puma/null_io.rb +1 -1
- data/lib/puma/plugin.rb +1 -10
- data/lib/puma/rack/builder.rb +0 -4
- data/lib/puma/reactor.rb +9 -4
- data/lib/puma/runner.rb +8 -36
- data/lib/puma/server.rb +149 -186
- data/lib/puma/single.rb +7 -64
- data/lib/puma/state_file.rb +6 -3
- data/lib/puma/thread_pool.rb +94 -49
- data/lib/rack/handler/puma.rb +1 -3
- data/tools/{docker/Dockerfile → Dockerfile} +0 -0
- metadata +21 -23
- data/docs/tcp_mode.md +0 -96
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
data/lib/puma/commonlogger.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Puma
|
4
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
5
5
|
# logs a line in the
|
6
|
-
# {Apache common log format}[
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/1.3/logs.html#common]
|
7
7
|
# to the +logger+.
|
8
8
|
#
|
9
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# (which is called without arguments in order to make the error appear for
|
17
17
|
# sure)
|
18
18
|
class CommonLogger
|
19
|
-
# Common Log Format:
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/1.3/logs.html#common
|
20
20
|
#
|
21
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
22
22
|
#
|
data/lib/puma/configuration.rb
CHANGED
@@ -54,9 +54,7 @@ module Puma
|
|
54
54
|
attr_reader :user_options, :file_options, :default_options
|
55
55
|
|
56
56
|
def [](key)
|
57
|
-
|
58
|
-
return file_options[key] if file_options.key?(key)
|
59
|
-
return default_options[key] if default_options.key?(key)
|
57
|
+
fetch(key)
|
60
58
|
end
|
61
59
|
|
62
60
|
def []=(key, value)
|
@@ -64,7 +62,11 @@ module Puma
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def fetch(key, default_value = nil)
|
67
|
-
|
65
|
+
return user_options[key] if user_options.key?(key)
|
66
|
+
return file_options[key] if file_options.key?(key)
|
67
|
+
return default_options[key] if default_options.key?(key)
|
68
|
+
|
69
|
+
default_value
|
68
70
|
end
|
69
71
|
|
70
72
|
def all_of(key)
|
@@ -106,7 +108,7 @@ module Puma
|
|
106
108
|
#
|
107
109
|
# It also handles loading plugins.
|
108
110
|
#
|
109
|
-
# > Note: `:port` and `:host` are not valid keys. By
|
111
|
+
# > Note: `:port` and `:host` are not valid keys. By the time they make it to the
|
110
112
|
# configuration options they are expected to be incorporated into a `:binds` key.
|
111
113
|
# Under the hood the DSL maps `port` and `host` calls to `:binds`
|
112
114
|
#
|
@@ -137,6 +139,10 @@ module Puma
|
|
137
139
|
@file_dsl = DSL.new(@options.file_options, self)
|
138
140
|
@default_dsl = DSL.new(@options.default_options, self)
|
139
141
|
|
142
|
+
if !@options[:prune_bundler]
|
143
|
+
default_options[:preload_app] = (@options[:workers] > 1) && Puma.forkable?
|
144
|
+
end
|
145
|
+
|
140
146
|
if block
|
141
147
|
configure(&block)
|
142
148
|
end
|
@@ -167,22 +173,26 @@ module Puma
|
|
167
173
|
self
|
168
174
|
end
|
169
175
|
|
176
|
+
# @version 5.0.0
|
177
|
+
def default_max_threads
|
178
|
+
Puma.mri? ? 5 : 16
|
179
|
+
end
|
180
|
+
|
170
181
|
def puma_default_options
|
171
182
|
{
|
172
|
-
:min_threads => 0,
|
173
|
-
:max_threads =>
|
183
|
+
:min_threads => Integer(ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS'] || 0),
|
184
|
+
:max_threads => Integer(ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS'] || default_max_threads),
|
174
185
|
:log_requests => false,
|
175
186
|
:debug => false,
|
176
187
|
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
|
177
|
-
:workers => 0,
|
178
|
-
:daemon => false,
|
188
|
+
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
179
189
|
:mode => :http,
|
180
190
|
:worker_timeout => DefaultWorkerTimeout,
|
181
191
|
:worker_boot_timeout => DefaultWorkerTimeout,
|
182
192
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
183
193
|
:remote_address => :socket,
|
184
194
|
:tag => method(:infer_tag),
|
185
|
-
:environment => -> { ENV['RACK_ENV'] || "development" },
|
195
|
+
:environment => -> { ENV['RACK_ENV'] || ENV['RAILS_ENV'] || "development" },
|
186
196
|
:rackup => DefaultRackup,
|
187
197
|
:logger => STDOUT,
|
188
198
|
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
@@ -245,14 +255,6 @@ module Puma
|
|
245
255
|
def app
|
246
256
|
found = options[:app] || load_rackup
|
247
257
|
|
248
|
-
if @options[:mode] == :tcp
|
249
|
-
require 'puma/tcp_logger'
|
250
|
-
|
251
|
-
logger = @options[:logger]
|
252
|
-
quiet = !@options[:log_requests]
|
253
|
-
return TCPLogger.new(logger, found, quiet)
|
254
|
-
end
|
255
|
-
|
256
258
|
if @options[:log_requests]
|
257
259
|
require 'puma/commonlogger'
|
258
260
|
logger = @options[:logger]
|
@@ -275,8 +277,15 @@ module Puma
|
|
275
277
|
@plugins.create name
|
276
278
|
end
|
277
279
|
|
278
|
-
def run_hooks(key, arg)
|
279
|
-
@options.all_of(key).each
|
280
|
+
def run_hooks(key, arg, events)
|
281
|
+
@options.all_of(key).each do |b|
|
282
|
+
begin
|
283
|
+
b.call arg
|
284
|
+
rescue => e
|
285
|
+
events.log "WARNING hook #{key} failed with exception (#{e.class}) #{e.message}"
|
286
|
+
events.debug e.backtrace.join("\n")
|
287
|
+
end
|
288
|
+
end
|
280
289
|
end
|
281
290
|
|
282
291
|
def self.temp_path
|
@@ -332,29 +341,9 @@ module Puma
|
|
332
341
|
end
|
333
342
|
|
334
343
|
def self.random_token
|
335
|
-
|
336
|
-
require 'openssl'
|
337
|
-
rescue LoadError
|
338
|
-
end
|
339
|
-
|
340
|
-
count = 16
|
341
|
-
|
342
|
-
bytes = nil
|
343
|
-
|
344
|
-
if defined? OpenSSL::Random
|
345
|
-
bytes = OpenSSL::Random.random_bytes(count)
|
346
|
-
elsif File.exist?("/dev/urandom")
|
347
|
-
File.open('/dev/urandom') { |f| bytes = f.read(count) }
|
348
|
-
end
|
349
|
-
|
350
|
-
if bytes
|
351
|
-
token = "".dup
|
352
|
-
bytes.each_byte { |b| token << b.to_s(16) }
|
353
|
-
else
|
354
|
-
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
355
|
-
end
|
344
|
+
require 'securerandom' unless defined?(SecureRandom)
|
356
345
|
|
357
|
-
|
346
|
+
SecureRandom.hex(16)
|
358
347
|
end
|
359
348
|
end
|
360
349
|
end
|
data/lib/puma/const.rb
CHANGED
@@ -100,8 +100,9 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "
|
104
|
-
CODE_NAME = "
|
103
|
+
PUMA_VERSION = VERSION = "5.0.0".freeze
|
104
|
+
CODE_NAME = "Spoony Bard".freeze
|
105
|
+
|
105
106
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
106
107
|
|
107
108
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
@@ -175,7 +176,6 @@ module Puma
|
|
175
176
|
PORT_443 = "443".freeze
|
176
177
|
LOCALHOST = "localhost".freeze
|
177
178
|
LOCALHOST_IP = "127.0.0.1".freeze
|
178
|
-
LOCALHOST_ADDR = "127.0.0.1:0".freeze
|
179
179
|
|
180
180
|
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
181
181
|
HTTP_11 = "HTTP/1.1".freeze
|
@@ -228,6 +228,7 @@ module Puma
|
|
228
228
|
COLON = ": ".freeze
|
229
229
|
|
230
230
|
NEWLINE = "\n".freeze
|
231
|
+
HTTP_INJECTION_REGEX = /[\r\n]/.freeze
|
231
232
|
|
232
233
|
HIJACK_P = "rack.hijack?".freeze
|
233
234
|
HIJACK = "rack.hijack".freeze
|
data/lib/puma/control_cli.rb
CHANGED
@@ -11,7 +11,10 @@ require 'socket'
|
|
11
11
|
module Puma
|
12
12
|
class ControlCLI
|
13
13
|
|
14
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
|
14
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats thread-backtraces refork}
|
15
|
+
|
16
|
+
# @version 5.0.0
|
17
|
+
PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}
|
15
18
|
|
16
19
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
17
20
|
@state = nil
|
@@ -22,7 +25,7 @@ module Puma
|
|
22
25
|
@control_auth_token = nil
|
23
26
|
@config_file = nil
|
24
27
|
@command = nil
|
25
|
-
@environment = ENV['RACK_ENV']
|
28
|
+
@environment = ENV['RACK_ENV'] || ENV['RAILS_ENV']
|
26
29
|
|
27
30
|
@argv = argv.dup
|
28
31
|
@stdout = stdout
|
@@ -81,6 +84,15 @@ module Puma
|
|
81
84
|
|
82
85
|
@command = argv.shift
|
83
86
|
|
87
|
+
# check presence of command
|
88
|
+
unless @command
|
89
|
+
raise "Available commands: #{COMMANDS.join(", ")}"
|
90
|
+
end
|
91
|
+
|
92
|
+
unless COMMANDS.include? @command
|
93
|
+
raise "Invalid command: #{@command}"
|
94
|
+
end
|
95
|
+
|
84
96
|
unless @config_file == '-'
|
85
97
|
environment = @environment || 'development'
|
86
98
|
|
@@ -99,16 +111,6 @@ module Puma
|
|
99
111
|
@pidfile ||= config.options[:pidfile]
|
100
112
|
end
|
101
113
|
end
|
102
|
-
|
103
|
-
# check present of command
|
104
|
-
unless @command
|
105
|
-
raise "Available commands: #{COMMANDS.join(", ")}"
|
106
|
-
end
|
107
|
-
|
108
|
-
unless COMMANDS.include? @command
|
109
|
-
raise "Invalid command: #{@command}"
|
110
|
-
end
|
111
|
-
|
112
114
|
rescue => e
|
113
115
|
@stdout.puts e.message
|
114
116
|
exit 1
|
@@ -145,8 +147,9 @@ module Puma
|
|
145
147
|
require 'openssl'
|
146
148
|
OpenSSL::SSL::SSLSocket.new(
|
147
149
|
TCPSocket.new(uri.host, uri.port),
|
148
|
-
OpenSSL::SSL::SSLContext.new
|
149
|
-
|
150
|
+
OpenSSL::SSL::SSLContext.new)
|
151
|
+
.tap { |ssl| ssl.sync_close = true } # default is false
|
152
|
+
.tap(&:connect)
|
150
153
|
when "tcp"
|
151
154
|
TCPSocket.new uri.host, uri.port
|
152
155
|
when "unix"
|
@@ -187,10 +190,16 @@ module Puma
|
|
187
190
|
end
|
188
191
|
|
189
192
|
message "Command #{@command} sent success"
|
190
|
-
message response.last if @command
|
193
|
+
message response.last if PRINTABLE_COMMANDS.include?(@command)
|
191
194
|
end
|
192
195
|
ensure
|
193
|
-
|
196
|
+
if server
|
197
|
+
if uri.scheme == "ssl"
|
198
|
+
server.sysclose
|
199
|
+
else
|
200
|
+
server.close unless server.closed?
|
201
|
+
end
|
202
|
+
end
|
194
203
|
end
|
195
204
|
|
196
205
|
def send_signal
|
@@ -231,6 +240,9 @@ module Puma
|
|
231
240
|
|
232
241
|
return
|
233
242
|
|
243
|
+
when "refork"
|
244
|
+
Process.kill "SIGURG", @pid
|
245
|
+
|
234
246
|
else
|
235
247
|
return
|
236
248
|
end
|
@@ -262,7 +274,7 @@ module Puma
|
|
262
274
|
exit 1
|
263
275
|
end
|
264
276
|
|
265
|
-
|
277
|
+
private
|
266
278
|
def start
|
267
279
|
require 'puma/cli'
|
268
280
|
|
data/lib/puma/detect.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Puma
|
4
|
+
# at present, MiniSSL::Engine is only defined in extension code, not in minissl.rb
|
5
|
+
HAS_SSL = const_defined?(:MiniSSL, false) && MiniSSL.const_defined?(:Engine, false)
|
6
|
+
|
7
|
+
def self.ssl?
|
8
|
+
HAS_SSL
|
9
|
+
end
|
10
|
+
|
4
11
|
IS_JRUBY = defined?(JRUBY_VERSION)
|
5
12
|
|
6
13
|
def self.jruby?
|
@@ -12,4 +19,14 @@ module Puma
|
|
12
19
|
def self.windows?
|
13
20
|
IS_WINDOWS
|
14
21
|
end
|
22
|
+
|
23
|
+
# @version 5.0.0
|
24
|
+
def self.mri?
|
25
|
+
RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
# @version 5.0.0
|
29
|
+
def self.forkable?
|
30
|
+
::Process.respond_to?(:fork)
|
31
|
+
end
|
15
32
|
end
|
data/lib/puma/dsl.rb
CHANGED
@@ -14,22 +14,23 @@ module Puma
|
|
14
14
|
# end
|
15
15
|
# config.load
|
16
16
|
#
|
17
|
-
# puts config.options[:binds]
|
18
|
-
# "tcp://127.0.0.1:3001"
|
17
|
+
# puts config.options[:binds] # => "tcp://127.0.0.1:3001"
|
19
18
|
#
|
20
19
|
# Used to load file:
|
21
20
|
#
|
22
21
|
# $ cat puma_config.rb
|
23
|
-
#
|
22
|
+
# port 3002
|
23
|
+
#
|
24
|
+
# Resulting configuration:
|
24
25
|
#
|
25
26
|
# config = Configuration.new(config_file: "puma_config.rb")
|
26
27
|
# config.load
|
27
28
|
#
|
28
|
-
# puts config.options[:binds]
|
29
|
-
# # => "tcp://127.0.0.1:3002"
|
29
|
+
# puts config.options[:binds] # => "tcp://127.0.0.1:3002"
|
30
30
|
#
|
31
31
|
# You can also find many examples being used by the test suite in
|
32
32
|
# +test/config+.
|
33
|
+
#
|
33
34
|
class DSL
|
34
35
|
include ConfigDefault
|
35
36
|
|
@@ -98,6 +99,9 @@ module Puma
|
|
98
99
|
# [body]
|
99
100
|
# ]
|
100
101
|
# end
|
102
|
+
#
|
103
|
+
# @see Puma::Configuration#app
|
104
|
+
#
|
101
105
|
def app(obj=nil, &block)
|
102
106
|
obj ||= block
|
103
107
|
|
@@ -160,12 +164,12 @@ module Puma
|
|
160
164
|
#
|
161
165
|
# You can use query parameters within the url to specify options:
|
162
166
|
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
167
|
+
# * Set the socket backlog depth with +backlog+, default is 1024.
|
168
|
+
# * Set up an SSL certificate with +key+ & +cert+.
|
169
|
+
# * Set whether to optimize for low latency instead of throughput with
|
170
|
+
# +low_latency+, default is to optimize for low latency. This is done
|
171
|
+
# via +Socket::TCP_NODELAY+.
|
172
|
+
# * Set socket permissions with +umask+.
|
169
173
|
#
|
170
174
|
# @example Backlog depth
|
171
175
|
# bind 'unix:///var/run/puma.sock?backlog=512'
|
@@ -175,6 +179,9 @@ module Puma
|
|
175
179
|
# bind 'tcp://0.0.0.0:9292?low_latency=false'
|
176
180
|
# @example Socket permissions
|
177
181
|
# bind 'unix:///var/run/puma.sock?umask=0111'
|
182
|
+
# @see Puma::Runner#load_and_bind
|
183
|
+
# @see Puma::Cluster#run
|
184
|
+
#
|
178
185
|
def bind(url)
|
179
186
|
@options[:binds] ||= []
|
180
187
|
@options[:binds] << url
|
@@ -193,13 +200,14 @@ module Puma
|
|
193
200
|
bind "tcp://#{host}:#{port}"
|
194
201
|
end
|
195
202
|
|
196
|
-
# Define how long persistent connections can be idle before Puma closes
|
197
|
-
#
|
203
|
+
# Define how long persistent connections can be idle before Puma closes them.
|
204
|
+
# @see Puma::Server.new
|
198
205
|
def persistent_timeout(seconds)
|
199
206
|
@options[:persistent_timeout] = Integer(seconds)
|
200
207
|
end
|
201
208
|
|
202
209
|
# Define how long the tcp socket stays open, if no data has been received.
|
210
|
+
# @see Puma::Server.new
|
203
211
|
def first_data_timeout(seconds)
|
204
212
|
@options[:first_data_timeout] = Integer(seconds)
|
205
213
|
end
|
@@ -210,24 +218,11 @@ module Puma
|
|
210
218
|
@options[:clean_thread_locals] = which
|
211
219
|
end
|
212
220
|
|
213
|
-
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
# @example
|
219
|
-
# daemonize
|
221
|
+
# When shutting down, drain the accept socket of pending connections and
|
222
|
+
# process them. This loops over the accept socket until there are no more
|
223
|
+
# read events and then stops looking and waits for the requests to finish.
|
224
|
+
# @see Puma::Server#graceful_shutdown
|
220
225
|
#
|
221
|
-
# @example
|
222
|
-
# daemonize false
|
223
|
-
def daemonize(which=true)
|
224
|
-
@options[:daemon] = which
|
225
|
-
end
|
226
|
-
|
227
|
-
# When shutting down, drain the accept socket of pending
|
228
|
-
# connections and process them. This loops over the accept
|
229
|
-
# socket until there are no more read events and then stops
|
230
|
-
# looking and waits for the requests to finish.
|
231
226
|
def drain_on_shutdown(which=true)
|
232
227
|
@options[:drain_on_shutdown] = which
|
233
228
|
end
|
@@ -250,6 +245,7 @@ module Puma
|
|
250
245
|
#
|
251
246
|
# Puma always waits a few seconds after killing a thread for it to try
|
252
247
|
# to finish up it's work, even in :immediately mode.
|
248
|
+
# @see Puma::Server#graceful_shutdown
|
253
249
|
def force_shutdown_after(val=:forever)
|
254
250
|
i = case val
|
255
251
|
when :forever
|
@@ -257,7 +253,7 @@ module Puma
|
|
257
253
|
when :immediately
|
258
254
|
0
|
259
255
|
else
|
260
|
-
|
256
|
+
Float(val)
|
261
257
|
end
|
262
258
|
|
263
259
|
@options[:force_shutdown_after] = i
|
@@ -322,20 +318,14 @@ module Puma
|
|
322
318
|
# @example
|
323
319
|
# rackup '/u/apps/lolcat/config.ru'
|
324
320
|
def rackup(path)
|
325
|
-
@options[:rackup]
|
326
|
-
end
|
327
|
-
|
328
|
-
# Run Puma in TCP mode
|
329
|
-
#
|
330
|
-
def tcp_mode!
|
331
|
-
@options[:mode] = :tcp
|
321
|
+
@options[:rackup] ||= path.to_s
|
332
322
|
end
|
333
323
|
|
334
324
|
def early_hints(answer=true)
|
335
325
|
@options[:early_hints] = answer
|
336
326
|
end
|
337
327
|
|
338
|
-
# Redirect STDOUT and STDERR to files specified. The +append+ parameter
|
328
|
+
# Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
|
339
329
|
# specifies whether the output is appended, the default is +false+.
|
340
330
|
#
|
341
331
|
# @example
|
@@ -376,8 +366,8 @@ module Puma
|
|
376
366
|
@options[:max_threads] = max
|
377
367
|
end
|
378
368
|
|
379
|
-
# Instead of
|
380
|
-
# can also use the
|
369
|
+
# Instead of `bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'` you
|
370
|
+
# can also use the this method.
|
381
371
|
#
|
382
372
|
# @example
|
383
373
|
# ssl_bind '127.0.0.1', '9292', {
|
@@ -419,12 +409,23 @@ module Puma
|
|
419
409
|
@options[:state] = path.to_s
|
420
410
|
end
|
421
411
|
|
412
|
+
# Use +permission+ to restrict permissions for the state file.
|
413
|
+
#
|
414
|
+
# @example
|
415
|
+
# state_permission 0600
|
416
|
+
# @version 5.0.0
|
417
|
+
#
|
418
|
+
def state_permission(permission)
|
419
|
+
@options[:state_permission] = permission
|
420
|
+
end
|
421
|
+
|
422
422
|
# How many worker processes to run. Typically this is set to
|
423
|
-
#
|
423
|
+
# the number of available cores.
|
424
424
|
#
|
425
425
|
# The default is 0.
|
426
426
|
#
|
427
427
|
# @note Cluster mode only.
|
428
|
+
# @see Puma::Cluster
|
428
429
|
def workers(count)
|
429
430
|
@options[:workers] = count.to_i
|
430
431
|
end
|
@@ -455,8 +456,8 @@ module Puma
|
|
455
456
|
#
|
456
457
|
# @note Cluster mode only.
|
457
458
|
# @example
|
458
|
-
#
|
459
|
-
# puts 'Before worker
|
459
|
+
# on_worker_boot do
|
460
|
+
# puts 'Before worker boot...'
|
460
461
|
# end
|
461
462
|
def on_worker_boot(&block)
|
462
463
|
@options[:before_worker_boot] ||= []
|
@@ -512,6 +513,29 @@ module Puma
|
|
512
513
|
|
513
514
|
alias_method :after_worker_boot, :after_worker_fork
|
514
515
|
|
516
|
+
# When `fork_worker` is enabled, code to run in Worker 0
|
517
|
+
# before all other workers are re-forked from this process,
|
518
|
+
# after the server has temporarily stopped serving requests
|
519
|
+
# (once per complete refork cycle).
|
520
|
+
#
|
521
|
+
# This can be used to trigger extra garbage-collection to maximize
|
522
|
+
# copy-on-write efficiency, or close any connections to remote servers
|
523
|
+
# (database, Redis, ...) that were opened while the server was running.
|
524
|
+
#
|
525
|
+
# This can be called multiple times to add several hooks.
|
526
|
+
#
|
527
|
+
# @note Cluster mode with `fork_worker` enabled only.
|
528
|
+
# @example
|
529
|
+
# on_refork do
|
530
|
+
# 3.times {GC.start}
|
531
|
+
# end
|
532
|
+
# @version 5.0.0
|
533
|
+
#
|
534
|
+
def on_refork(&block)
|
535
|
+
@options[:before_refork] ||= []
|
536
|
+
@options[:before_refork] << block
|
537
|
+
end
|
538
|
+
|
515
539
|
# Code to run out-of-band when the worker is idle.
|
516
540
|
# These hooks run immediately after a request has finished
|
517
541
|
# processing and there are no busy threads on the worker.
|
@@ -536,17 +560,6 @@ module Puma
|
|
536
560
|
@options[:directory] = dir.to_s
|
537
561
|
end
|
538
562
|
|
539
|
-
# DEPRECATED: The directory to operate out of.
|
540
|
-
def worker_directory(dir)
|
541
|
-
$stderr.puts "worker_directory is deprecated. Please use `directory`"
|
542
|
-
directory dir
|
543
|
-
end
|
544
|
-
|
545
|
-
# Run the app as a raw TCP app instead of an HTTP rack app.
|
546
|
-
def tcp_mode
|
547
|
-
@options[:mode] = :tcp
|
548
|
-
end
|
549
|
-
|
550
563
|
# Preload the application before starting the workers; this conflicts with
|
551
564
|
# phased restart feature. This is off by default.
|
552
565
|
#
|
@@ -583,7 +596,7 @@ module Puma
|
|
583
596
|
# new Bundler context and thus can float around as the release
|
584
597
|
# dictates.
|
585
598
|
#
|
586
|
-
#
|
599
|
+
# @see extra_runtime_dependencies
|
587
600
|
#
|
588
601
|
# @note This is incompatible with +preload_app!+.
|
589
602
|
# @note This is only supported for RubyGems 2.2+
|
@@ -600,6 +613,9 @@ module Puma
|
|
600
613
|
#
|
601
614
|
# @example
|
602
615
|
# raise_exception_on_sigterm false
|
616
|
+
# @see Puma::Launcher#setup_signals
|
617
|
+
# @see Puma::Cluster#setup_signals
|
618
|
+
#
|
603
619
|
def raise_exception_on_sigterm(answer=true)
|
604
620
|
@options[:raise_exception_on_sigterm] = answer
|
605
621
|
end
|
@@ -615,6 +631,8 @@ module Puma
|
|
615
631
|
# extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
|
616
632
|
# @example
|
617
633
|
# extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
|
634
|
+
# @see Puma::Launcher#extra_runtime_deps_directories
|
635
|
+
#
|
618
636
|
def extra_runtime_dependencies(answer = [])
|
619
637
|
@options[:extra_runtime_dependencies] = Array(answer)
|
620
638
|
end
|
@@ -642,6 +660,8 @@ module Puma
|
|
642
660
|
# @note Cluster mode only.
|
643
661
|
# @example
|
644
662
|
# worker_timeout 60
|
663
|
+
# @see Puma::Cluster::Worker#ping_timeout
|
664
|
+
#
|
645
665
|
def worker_timeout(timeout)
|
646
666
|
timeout = Integer(timeout)
|
647
667
|
min = Const::WORKER_CHECK_INTERVAL
|
@@ -658,15 +678,20 @@ module Puma
|
|
658
678
|
# If unspecified, this defaults to the value of worker_timeout.
|
659
679
|
#
|
660
680
|
# @note Cluster mode only.
|
661
|
-
#
|
681
|
+
#
|
682
|
+
# @example
|
662
683
|
# worker_boot_timeout 60
|
684
|
+
# @see Puma::Cluster::Worker#ping_timeout
|
685
|
+
#
|
663
686
|
def worker_boot_timeout(timeout)
|
664
687
|
@options[:worker_boot_timeout] = Integer(timeout)
|
665
688
|
end
|
666
689
|
|
667
|
-
# Set the timeout for worker shutdown
|
690
|
+
# Set the timeout for worker shutdown.
|
668
691
|
#
|
669
692
|
# @note Cluster mode only.
|
693
|
+
# @see Puma::Cluster::Worker#term
|
694
|
+
#
|
670
695
|
def worker_shutdown_timeout(timeout)
|
671
696
|
@options[:worker_shutdown_timeout] = Integer(timeout)
|
672
697
|
end
|
@@ -684,6 +709,7 @@ module Puma
|
|
684
709
|
# slow clients will occupy a handler thread while the request
|
685
710
|
# is being sent. A reverse proxy, such as nginx, can handle
|
686
711
|
# slow clients and queue requests before they reach Puma.
|
712
|
+
# @see Puma::Server
|
687
713
|
def queue_requests(answer=true)
|
688
714
|
@options[:queue_requests] = answer
|
689
715
|
end
|
@@ -691,10 +717,25 @@ module Puma
|
|
691
717
|
# When a shutdown is requested, the backtraces of all the
|
692
718
|
# threads will be written to $stdout. This can help figure
|
693
719
|
# out why shutdown is hanging.
|
720
|
+
#
|
694
721
|
def shutdown_debug(val=true)
|
695
722
|
@options[:shutdown_debug] = val
|
696
723
|
end
|
697
724
|
|
725
|
+
|
726
|
+
# Attempts to route traffic to less-busy workers by causing them to delay
|
727
|
+
# listening on the socket, allowing workers which are not processing any
|
728
|
+
# requests to pick up new requests first.
|
729
|
+
#
|
730
|
+
# Only works on MRI. For all other interpreters, this setting does nothing.
|
731
|
+
# @see Puma::Server#handle_servers
|
732
|
+
# @see Puma::ThreadPool#wait_for_less_busy_worker
|
733
|
+
# @version 5.0.0
|
734
|
+
#
|
735
|
+
def wait_for_less_busy_worker(val=0.005)
|
736
|
+
@options[:wait_for_less_busy_worker] = val.to_f
|
737
|
+
end
|
738
|
+
|
698
739
|
# Control how the remote address of the connection is set. This
|
699
740
|
# is configurable because to calculate the true socket peer address
|
700
741
|
# a kernel syscall is required which for very fast rack handlers
|
@@ -702,18 +743,18 @@ module Puma
|
|
702
743
|
#
|
703
744
|
# There are 4 possible values:
|
704
745
|
#
|
705
|
-
#
|
706
|
-
#
|
707
|
-
#
|
708
|
-
#
|
709
|
-
#
|
710
|
-
#
|
711
|
-
#
|
712
|
-
#
|
713
|
-
#
|
714
|
-
#
|
715
|
-
#
|
716
|
-
#
|
746
|
+
# 1. **:socket** (the default) - read the peername from the socket using the
|
747
|
+
# syscall. This is the normal behavior.
|
748
|
+
# 2. **:localhost** - set the remote address to "127.0.0.1"
|
749
|
+
# 3. **header: <http_header>**- set the remote address to the value of the
|
750
|
+
# provided http header. For instance:
|
751
|
+
# `set_remote_address header: "X-Real-IP"`.
|
752
|
+
# Only the first word (as separated by spaces or comma) is used, allowing
|
753
|
+
# headers such as X-Forwarded-For to be used as well.
|
754
|
+
# 4. **\<Any string\>** - this allows you to hardcode remote address to any value
|
755
|
+
# you wish. Because Puma never uses this field anyway, it's format is
|
756
|
+
# entirely in your hands.
|
757
|
+
#
|
717
758
|
def set_remote_address(val=:socket)
|
718
759
|
case val
|
719
760
|
when :socket
|
@@ -736,5 +777,38 @@ module Puma
|
|
736
777
|
end
|
737
778
|
end
|
738
779
|
|
780
|
+
# When enabled, workers will be forked from worker 0 instead of from the master process.
|
781
|
+
# This option is similar to `preload_app` because the app is preloaded before forking,
|
782
|
+
# but it is compatible with phased restart.
|
783
|
+
#
|
784
|
+
# This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
|
785
|
+
# in a running app.
|
786
|
+
#
|
787
|
+
# A refork will automatically trigger once after the specified number of requests
|
788
|
+
# (default 1000), or pass 0 to disable auto refork.
|
789
|
+
#
|
790
|
+
# @note Cluster mode only.
|
791
|
+
# @version 5.0.0
|
792
|
+
#
|
793
|
+
def fork_worker(after_requests=1000)
|
794
|
+
@options[:fork_worker] = Integer(after_requests)
|
795
|
+
end
|
796
|
+
|
797
|
+
# When enabled, Puma will GC 4 times before forking workers.
|
798
|
+
# If available (Ruby 2.7+), we will also call GC.compact.
|
799
|
+
# Not recommended for non-MRI Rubies.
|
800
|
+
#
|
801
|
+
# Based on the work of Koichi Sasada and Aaron Patterson, this option may
|
802
|
+
# decrease memory utilization of preload-enabled cluster-mode Pumas. It will
|
803
|
+
# also increase time to boot and fork. See your logs for details on how much
|
804
|
+
# time this adds to your boot process. For most apps, it will be less than one
|
805
|
+
# second.
|
806
|
+
#
|
807
|
+
# @see Puma::Cluster#nakayoshi_gc
|
808
|
+
# @version 5.0.0
|
809
|
+
#
|
810
|
+
def nakayoshi_fork(enabled=true)
|
811
|
+
@options[:nakayoshi_fork] = enabled
|
812
|
+
end
|
739
813
|
end
|
740
814
|
end
|