puma 5.5.0 → 5.6.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.
- checksums.yaml +4 -4
- data/History.md +72 -0
- data/LICENSE +0 -0
- data/README.md +28 -6
- data/bin/puma-wild +0 -0
- data/docs/architecture.md +49 -16
- data/docs/compile_options.md +4 -2
- data/docs/deployment.md +53 -52
- data/docs/fork_worker.md +0 -0
- 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 +63 -67
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +12 -6
- data/ext/puma_http11/http11_parser.c +23 -10
- data/ext/puma_http11/http11_parser.h +0 -0
- data/ext/puma_http11/http11_parser.java.rl +0 -0
- data/ext/puma_http11/http11_parser.rl +0 -0
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +54 -9
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +49 -47
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +28 -43
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma/app/status.rb +0 -0
- data/lib/puma/binder.rb +19 -5
- data/lib/puma/cli.rb +9 -4
- data/lib/puma/client.rb +2 -2
- data/lib/puma/cluster/worker.rb +7 -17
- data/lib/puma/cluster/worker_handle.rb +4 -0
- data/lib/puma/cluster.rb +29 -21
- data/lib/puma/commonlogger.rb +0 -0
- data/lib/puma/configuration.rb +4 -1
- data/lib/puma/const.rb +2 -5
- data/lib/puma/control_cli.rb +1 -1
- data/lib/puma/detect.rb +8 -2
- data/lib/puma/dsl.rb +85 -8
- data/lib/puma/error_logger.rb +0 -0
- data/lib/puma/events.rb +0 -0
- data/lib/puma/io_buffer.rb +0 -0
- data/lib/puma/jruby_restart.rb +0 -0
- data/lib/puma/json_serialization.rb +0 -0
- data/lib/puma/launcher.rb +2 -1
- data/lib/puma/minissl/context_builder.rb +8 -6
- data/lib/puma/minissl.rb +19 -3
- data/lib/puma/null_io.rb +0 -0
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +1 -1
- data/lib/puma/queue_close.rb +0 -0
- data/lib/puma/rack/builder.rb +0 -0
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +0 -0
- data/lib/puma/reactor.rb +0 -0
- data/lib/puma/request.rb +0 -0
- data/lib/puma/runner.rb +22 -8
- data/lib/puma/server.rb +24 -30
- data/lib/puma/single.rb +0 -0
- data/lib/puma/state_file.rb +41 -7
- data/lib/puma/systemd.rb +0 -0
- data/lib/puma/thread_pool.rb +2 -2
- data/lib/puma/util.rb +7 -0
- data/lib/puma.rb +0 -0
- data/lib/rack/handler/puma.rb +0 -0
- data/tools/Dockerfile +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +3 -3
data/lib/puma/detect.rb
CHANGED
@@ -10,8 +10,10 @@ module Puma
|
|
10
10
|
|
11
11
|
IS_JRUBY = Object.const_defined? :JRUBY_VERSION
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
IS_OSX = RUBY_PLATFORM.include? 'darwin'
|
14
|
+
|
15
|
+
IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/) ||
|
16
|
+
IS_JRUBY && RUBY_DESCRIPTION.include?('mswin')
|
15
17
|
|
16
18
|
# @version 5.2.0
|
17
19
|
IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
|
@@ -20,6 +22,10 @@ module Puma
|
|
20
22
|
IS_JRUBY
|
21
23
|
end
|
22
24
|
|
25
|
+
def self.osx?
|
26
|
+
IS_OSX
|
27
|
+
end
|
28
|
+
|
23
29
|
def self.windows?
|
24
30
|
IS_WINDOWS
|
25
31
|
end
|
data/lib/puma/dsl.rb
CHANGED
@@ -48,6 +48,8 @@ module Puma
|
|
48
48
|
|
49
49
|
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
50
50
|
|
51
|
+
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
52
|
+
|
51
53
|
if defined?(JRUBY_VERSION)
|
52
54
|
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
53
55
|
"&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
|
@@ -55,7 +57,7 @@ module Puma
|
|
55
57
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
56
58
|
|
57
59
|
"ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
|
58
|
-
"&verify_mode=#{verify}#{tls_str}#{ca_additions}"
|
60
|
+
"&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
|
59
61
|
else
|
60
62
|
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
61
63
|
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
@@ -64,7 +66,7 @@ module Puma
|
|
64
66
|
"&verification_flags=#{Array(ary).join ','}" : nil
|
65
67
|
|
66
68
|
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
|
67
|
-
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
|
69
|
+
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
@@ -191,7 +193,7 @@ module Puma
|
|
191
193
|
end
|
192
194
|
|
193
195
|
# Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
|
194
|
-
# accepted protocols. Multiple urls can be bound to, calling
|
196
|
+
# accepted protocols. Multiple urls can be bound to, calling +bind+ does
|
195
197
|
# not overwrite previous bindings.
|
196
198
|
#
|
197
199
|
# The default is "tcp://0.0.0.0:9292".
|
@@ -436,8 +438,15 @@ module Puma
|
|
436
438
|
@options[:max_threads] = max
|
437
439
|
end
|
438
440
|
|
439
|
-
# Instead of
|
440
|
-
#
|
441
|
+
# Instead of using +bind+ and manually constructing a URI like:
|
442
|
+
#
|
443
|
+
# bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
|
444
|
+
#
|
445
|
+
# you can use the this method.
|
446
|
+
#
|
447
|
+
# When binding on localhost you don't need to specify +cert+ and +key+,
|
448
|
+
# Puma will assume you are using the +localhost+ gem and try to load the
|
449
|
+
# appropriate files.
|
441
450
|
#
|
442
451
|
# @example
|
443
452
|
# ssl_bind '127.0.0.1', '9292', {
|
@@ -447,14 +456,25 @@ module Puma
|
|
447
456
|
# verify_mode: verify_mode, # default 'none'
|
448
457
|
# verification_flags: flags, # optional, not supported by JRuby
|
449
458
|
# }
|
450
|
-
#
|
459
|
+
#
|
460
|
+
# @example Using self-signed certificate with the +localhost+ gem:
|
461
|
+
# ssl_bind '127.0.0.1', '9292'
|
462
|
+
#
|
463
|
+
# @example Alternatively, you can provide +cert_pem+ and +key_pem+:
|
464
|
+
# ssl_bind '127.0.0.1', '9292', {
|
465
|
+
# cert_pem: File.read(path_to_cert),
|
466
|
+
# key_pem: File.read(path_to_key),
|
467
|
+
# }
|
468
|
+
#
|
469
|
+
# @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
|
451
470
|
# ssl_bind '127.0.0.1', '9292', {
|
452
471
|
# keystore: path_to_keystore,
|
453
472
|
# keystore_pass: password,
|
454
473
|
# ssl_cipher_list: cipher_list, # optional
|
455
474
|
# verify_mode: verify_mode # default 'none'
|
456
475
|
# }
|
457
|
-
def ssl_bind(host, port, opts)
|
476
|
+
def ssl_bind(host, port, opts = {})
|
477
|
+
add_pem_values_to_options_store(opts)
|
458
478
|
bind self.class.ssl_bind_str(host, port, opts)
|
459
479
|
end
|
460
480
|
|
@@ -727,6 +747,19 @@ module Puma
|
|
727
747
|
@options[:tag] = string.to_s
|
728
748
|
end
|
729
749
|
|
750
|
+
# Change the default interval for checking workers.
|
751
|
+
#
|
752
|
+
# The default value is 5 seconds.
|
753
|
+
#
|
754
|
+
# @note Cluster mode only.
|
755
|
+
# @example
|
756
|
+
# worker_check_interval 5
|
757
|
+
# @see Puma::Cluster#check_workers
|
758
|
+
#
|
759
|
+
def worker_check_interval(interval)
|
760
|
+
@options[:worker_check_interval] = Integer(interval)
|
761
|
+
end
|
762
|
+
|
730
763
|
# Verifies that all workers have checked in to the master process within
|
731
764
|
# the given timeout. If not the worker process will be restarted. This is
|
732
765
|
# not a request timeout, it is to protect against a hung or dead process.
|
@@ -741,7 +774,7 @@ module Puma
|
|
741
774
|
#
|
742
775
|
def worker_timeout(timeout)
|
743
776
|
timeout = Integer(timeout)
|
744
|
-
min =
|
777
|
+
min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
|
745
778
|
|
746
779
|
if timeout <= min
|
747
780
|
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
@@ -773,6 +806,30 @@ module Puma
|
|
773
806
|
@options[:worker_shutdown_timeout] = Integer(timeout)
|
774
807
|
end
|
775
808
|
|
809
|
+
# Set the strategy for worker culling.
|
810
|
+
#
|
811
|
+
# There are two possible values:
|
812
|
+
#
|
813
|
+
# 1. **:youngest** - the youngest workers (i.e. the workers that were
|
814
|
+
# the most recently started) will be culled.
|
815
|
+
# 2. **:oldest** - the oldest workers (i.e. the workers that were started
|
816
|
+
# the longest time ago) will be culled.
|
817
|
+
#
|
818
|
+
# @note Cluster mode only.
|
819
|
+
# @example
|
820
|
+
# worker_culling_strategy :oldest
|
821
|
+
# @see Puma::Cluster#cull_workers
|
822
|
+
#
|
823
|
+
def worker_culling_strategy(strategy)
|
824
|
+
stategy = strategy.to_sym
|
825
|
+
|
826
|
+
if ![:youngest, :oldest].include?(strategy)
|
827
|
+
raise "Invalid value for worker_culling_strategy - #{stategy}"
|
828
|
+
end
|
829
|
+
|
830
|
+
@options[:worker_culling_strategy] = strategy
|
831
|
+
end
|
832
|
+
|
776
833
|
# When set to true (the default), workers accept all requests
|
777
834
|
# and queue them before passing them to the handlers.
|
778
835
|
# When set to false, each worker process accepts exactly as
|
@@ -927,5 +984,25 @@ module Puma
|
|
927
984
|
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
|
928
985
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
929
986
|
end
|
987
|
+
|
988
|
+
private
|
989
|
+
|
990
|
+
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
991
|
+
# options[:store] from where Puma binder knows how to find and extract them.
|
992
|
+
def add_pem_values_to_options_store(opts)
|
993
|
+
return if defined?(JRUBY_VERSION)
|
994
|
+
|
995
|
+
@options[:store] ||= []
|
996
|
+
|
997
|
+
# Store cert_pem and key_pem to options[:store] if present
|
998
|
+
[:cert, :key].each do |v|
|
999
|
+
opt_key = :"#{v}_pem"
|
1000
|
+
if opts[opt_key]
|
1001
|
+
index = @options[:store].length
|
1002
|
+
@options[:store] << opts[opt_key]
|
1003
|
+
opts[v] = "store:#{index}"
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
end
|
930
1007
|
end
|
931
1008
|
end
|
data/lib/puma/error_logger.rb
CHANGED
File without changes
|
data/lib/puma/events.rb
CHANGED
File without changes
|
data/lib/puma/io_buffer.rb
CHANGED
File without changes
|
data/lib/puma/jruby_restart.rb
CHANGED
File without changes
|
File without changes
|
data/lib/puma/launcher.rb
CHANGED
@@ -15,6 +15,7 @@ module Puma
|
|
15
15
|
# It is responsible for either launching a cluster of Puma workers or a single
|
16
16
|
# puma server.
|
17
17
|
class Launcher
|
18
|
+
# @deprecated 6.0.0
|
18
19
|
KEYS_NOT_TO_PERSIST_IN_STATE = [
|
19
20
|
:logger, :lowlevel_error_handler,
|
20
21
|
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
@@ -73,7 +74,7 @@ module Puma
|
|
73
74
|
|
74
75
|
generate_restart_data
|
75
76
|
|
76
|
-
if clustered? && !
|
77
|
+
if clustered? && !Puma.forkable?
|
77
78
|
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
78
79
|
end
|
79
80
|
|
@@ -23,17 +23,19 @@ module Puma
|
|
23
23
|
ctx.keystore_pass = params['keystore-pass']
|
24
24
|
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
25
25
|
else
|
26
|
-
|
27
|
-
events.error "Please specify the SSL key via 'key='"
|
26
|
+
if params['key'].nil? && params['key_pem'].nil?
|
27
|
+
events.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
28
28
|
end
|
29
29
|
|
30
|
-
ctx.key = params['key']
|
30
|
+
ctx.key = params['key'] if params['key']
|
31
|
+
ctx.key_pem = params['key_pem'] if params['key_pem']
|
31
32
|
|
32
|
-
|
33
|
-
events.error "Please specify the SSL cert via 'cert='"
|
33
|
+
if params['cert'].nil? && params['cert_pem'].nil?
|
34
|
+
events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
34
35
|
end
|
35
36
|
|
36
|
-
ctx.cert = params['cert']
|
37
|
+
ctx.cert = params['cert'] if params['cert']
|
38
|
+
ctx.cert_pem = params['cert_pem'] if params['cert_pem']
|
37
39
|
|
38
40
|
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
39
41
|
unless params['ca']
|
data/lib/puma/minissl.rb
CHANGED
@@ -169,7 +169,7 @@ module Puma
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
rescue IOError, SystemCallError
|
172
|
-
|
172
|
+
Puma::Util.purge_interrupt_queue
|
173
173
|
# nothing
|
174
174
|
ensure
|
175
175
|
@socket.close
|
@@ -208,6 +208,10 @@ module Puma
|
|
208
208
|
def initialize
|
209
209
|
@no_tlsv1 = false
|
210
210
|
@no_tlsv1_1 = false
|
211
|
+
@key = nil
|
212
|
+
@cert = nil
|
213
|
+
@key_pem = nil
|
214
|
+
@cert_pem = nil
|
211
215
|
end
|
212
216
|
|
213
217
|
if IS_JRUBY
|
@@ -230,6 +234,8 @@ module Puma
|
|
230
234
|
attr_reader :key
|
231
235
|
attr_reader :cert
|
232
236
|
attr_reader :ca
|
237
|
+
attr_reader :cert_pem
|
238
|
+
attr_reader :key_pem
|
233
239
|
attr_accessor :ssl_cipher_filter
|
234
240
|
attr_accessor :verification_flags
|
235
241
|
|
@@ -248,9 +254,19 @@ module Puma
|
|
248
254
|
@ca = ca
|
249
255
|
end
|
250
256
|
|
257
|
+
def cert_pem=(cert_pem)
|
258
|
+
raise ArgumentError, "'cert_pem' is not a String" unless cert_pem.is_a? String
|
259
|
+
@cert_pem = cert_pem
|
260
|
+
end
|
261
|
+
|
262
|
+
def key_pem=(key_pem)
|
263
|
+
raise ArgumentError, "'key_pem' is not a String" unless key_pem.is_a? String
|
264
|
+
@key_pem = key_pem
|
265
|
+
end
|
266
|
+
|
251
267
|
def check
|
252
|
-
raise "Key not configured"
|
253
|
-
raise "Cert not configured"
|
268
|
+
raise "Key not configured" if @key.nil? && @key_pem.nil?
|
269
|
+
raise "Cert not configured" if @cert.nil? && @cert_pem.nil?
|
254
270
|
end
|
255
271
|
end
|
256
272
|
|
data/lib/puma/null_io.rb
CHANGED
File without changes
|
File without changes
|
data/lib/puma/plugin.rb
CHANGED
data/lib/puma/queue_close.rb
CHANGED
File without changes
|
data/lib/puma/rack/builder.rb
CHANGED
File without changes
|
data/lib/puma/rack/urlmap.rb
CHANGED
File without changes
|
data/lib/puma/rack_default.rb
CHANGED
File without changes
|
data/lib/puma/reactor.rb
CHANGED
File without changes
|
data/lib/puma/request.rb
CHANGED
File without changes
|
data/lib/puma/runner.rb
CHANGED
@@ -15,6 +15,16 @@ module Puma
|
|
15
15
|
@app = nil
|
16
16
|
@control = nil
|
17
17
|
@started_at = Time.now
|
18
|
+
@wakeup = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def wakeup!
|
22
|
+
return unless @wakeup
|
23
|
+
|
24
|
+
@wakeup.write "!" unless @wakeup.closed?
|
25
|
+
|
26
|
+
rescue SystemCallError, IOError
|
27
|
+
Puma::Util.purge_interrupt_queue
|
18
28
|
end
|
19
29
|
|
20
30
|
def development?
|
@@ -59,7 +69,7 @@ module Puma
|
|
59
69
|
|
60
70
|
control.binder.parse [str], self, 'Starting control server'
|
61
71
|
|
62
|
-
control.run thread_name: '
|
72
|
+
control.run thread_name: 'ctl'
|
63
73
|
@control = control
|
64
74
|
end
|
65
75
|
|
@@ -84,12 +94,13 @@ module Puma
|
|
84
94
|
def output_header(mode)
|
85
95
|
min_t = @options[:min_threads]
|
86
96
|
max_t = @options[:max_threads]
|
97
|
+
environment = @options[:environment]
|
87
98
|
|
88
99
|
log "Puma starting in #{mode} mode..."
|
89
100
|
log "* Puma version: #{Puma::Const::PUMA_VERSION} (#{ruby_engine}) (\"#{Puma::Const::CODE_NAME}\")"
|
90
101
|
log "* Min threads: #{min_t}"
|
91
102
|
log "* Max threads: #{max_t}"
|
92
|
-
log "* Environment: #{
|
103
|
+
log "* Environment: #{environment}"
|
93
104
|
|
94
105
|
if mode == "cluster"
|
95
106
|
log "* Master PID: #{Process.pid}"
|
@@ -108,9 +119,7 @@ module Puma
|
|
108
119
|
append = @options[:redirect_append]
|
109
120
|
|
110
121
|
if stdout
|
111
|
-
|
112
|
-
raise "Cannot redirect STDOUT to #{stdout}"
|
113
|
-
end
|
122
|
+
ensure_output_directory_exists(stdout, 'STDOUT')
|
114
123
|
|
115
124
|
STDOUT.reopen stdout, (append ? "a" : "w")
|
116
125
|
STDOUT.puts "=== puma startup: #{Time.now} ==="
|
@@ -118,9 +127,7 @@ module Puma
|
|
118
127
|
end
|
119
128
|
|
120
129
|
if stderr
|
121
|
-
|
122
|
-
raise "Cannot redirect STDERR to #{stderr}"
|
123
|
-
end
|
130
|
+
ensure_output_directory_exists(stderr, 'STDERR')
|
124
131
|
|
125
132
|
STDERR.reopen stderr, (append ? "a" : "w")
|
126
133
|
STDERR.puts "=== puma startup: #{Time.now} ==="
|
@@ -159,5 +166,12 @@ module Puma
|
|
159
166
|
server.inherit_binder @launcher.binder
|
160
167
|
server
|
161
168
|
end
|
169
|
+
|
170
|
+
private
|
171
|
+
def ensure_output_directory_exists(path, io_name)
|
172
|
+
unless Dir.exist?(File.dirname(path))
|
173
|
+
raise "Cannot redirect #{io_name} to #{path}"
|
174
|
+
end
|
175
|
+
end
|
162
176
|
end
|
163
177
|
end
|
data/lib/puma/server.rb
CHANGED
@@ -146,7 +146,7 @@ module Puma
|
|
146
146
|
begin
|
147
147
|
skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 1) if skt.kind_of? TCPSocket
|
148
148
|
rescue IOError, SystemCallError
|
149
|
-
|
149
|
+
Puma::Util.purge_interrupt_queue
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -155,7 +155,7 @@ module Puma
|
|
155
155
|
begin
|
156
156
|
skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 0) if skt.kind_of? TCPSocket
|
157
157
|
rescue IOError, SystemCallError
|
158
|
-
|
158
|
+
Puma::Util.purge_interrupt_queue
|
159
159
|
end
|
160
160
|
end
|
161
161
|
else
|
@@ -176,7 +176,7 @@ module Puma
|
|
176
176
|
begin
|
177
177
|
tcp_info = skt.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_INFO)
|
178
178
|
rescue IOError, SystemCallError
|
179
|
-
|
179
|
+
Puma::Util.purge_interrupt_queue
|
180
180
|
@precheck_closing = false
|
181
181
|
false
|
182
182
|
else
|
@@ -220,7 +220,7 @@ module Puma
|
|
220
220
|
# up in the background to handle requests. Otherwise requests
|
221
221
|
# are handled synchronously.
|
222
222
|
#
|
223
|
-
def run(background=true, thread_name: '
|
223
|
+
def run(background=true, thread_name: 'srv')
|
224
224
|
BasicSocket.do_not_reverse_lookup = true
|
225
225
|
|
226
226
|
@events.fire :state, :booting
|
@@ -315,16 +315,15 @@ module Puma
|
|
315
315
|
queue_requests = @queue_requests
|
316
316
|
drain = @options[:drain_on_shutdown] ? 0 : nil
|
317
317
|
|
318
|
-
|
319
|
-
remote_addr_header = nil
|
320
|
-
|
321
|
-
case @options[:remote_address]
|
318
|
+
addr_send_name, addr_value = case @options[:remote_address]
|
322
319
|
when :value
|
323
|
-
|
320
|
+
[:peerip=, @options[:remote_address_value]]
|
324
321
|
when :header
|
325
|
-
remote_addr_header
|
322
|
+
[:remote_addr_header=, @options[:remote_address_header]]
|
326
323
|
when :proxy_protocol
|
327
|
-
|
324
|
+
[:expect_proxy_proto=, @options[:remote_address_proxy_protocol]]
|
325
|
+
else
|
326
|
+
[nil, nil]
|
328
327
|
end
|
329
328
|
|
330
329
|
while @status == :run || (drain && shutting_down?)
|
@@ -344,16 +343,10 @@ module Puma
|
|
344
343
|
next
|
345
344
|
end
|
346
345
|
drain += 1 if shutting_down?
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
elsif remote_addr_header
|
352
|
-
client.remote_addr_header = remote_addr_header
|
353
|
-
elsif remote_addr_proxy_protocol
|
354
|
-
client.expect_proxy_proto = remote_addr_proxy_protocol
|
355
|
-
end
|
356
|
-
pool << client
|
346
|
+
pool << Client.new(io, @binder.env(sock)).tap { |c|
|
347
|
+
c.listener = sock
|
348
|
+
c.send(addr_send_name, addr_value) if addr_value
|
349
|
+
}
|
357
350
|
end
|
358
351
|
end
|
359
352
|
rescue IOError, Errno::EBADF
|
@@ -375,13 +368,14 @@ module Puma
|
|
375
368
|
rescue Exception => e
|
376
369
|
@events.unknown_error e, nil, "Exception handling servers"
|
377
370
|
ensure
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
371
|
+
# RuntimeError is Ruby 2.2 issue, can't modify frozen IOError
|
372
|
+
# Errno::EBADF is infrequently raised
|
373
|
+
[@check, @notify].each do |io|
|
374
|
+
begin
|
375
|
+
io.close unless io.closed?
|
376
|
+
rescue Errno::EBADF, RuntimeError
|
377
|
+
end
|
383
378
|
end
|
384
|
-
@notify.close
|
385
379
|
@notify = nil
|
386
380
|
@check = nil
|
387
381
|
end
|
@@ -491,7 +485,7 @@ module Puma
|
|
491
485
|
begin
|
492
486
|
client.close if close_socket
|
493
487
|
rescue IOError, SystemCallError
|
494
|
-
|
488
|
+
Puma::Util.purge_interrupt_queue
|
495
489
|
# Already closed
|
496
490
|
rescue StandardError => e
|
497
491
|
@events.unknown_error e, nil, "Client"
|
@@ -583,11 +577,11 @@ module Puma
|
|
583
577
|
@notify << message
|
584
578
|
rescue IOError, NoMethodError, Errno::EPIPE
|
585
579
|
# The server, in another thread, is shutting down
|
586
|
-
|
580
|
+
Puma::Util.purge_interrupt_queue
|
587
581
|
rescue RuntimeError => e
|
588
582
|
# Temporary workaround for https://bugs.ruby-lang.org/issues/13239
|
589
583
|
if e.message.include?('IOError')
|
590
|
-
|
584
|
+
Puma::Util.purge_interrupt_queue
|
591
585
|
else
|
592
586
|
raise e
|
593
587
|
end
|
data/lib/puma/single.rb
CHANGED
File without changes
|
data/lib/puma/state_file.rb
CHANGED
@@ -1,15 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'yaml'
|
4
|
-
|
5
3
|
module Puma
|
4
|
+
|
5
|
+
# Puma::Launcher uses StateFile to write a yaml file for use with Puma::ControlCLI.
|
6
|
+
#
|
7
|
+
# In previous versions of Puma, YAML was used to read/write the state file.
|
8
|
+
# Since Puma is similar to Bundler/RubyGems in that it may load before one's app
|
9
|
+
# does, minimizing the dependencies that may be shared with the app is desired.
|
10
|
+
#
|
11
|
+
# At present, it only works with numeric and string values. It is still a valid
|
12
|
+
# yaml file, and the CI tests parse it with Psych.
|
13
|
+
#
|
6
14
|
class StateFile
|
15
|
+
|
16
|
+
ALLOWED_FIELDS = %w!control_url control_auth_token pid running_from!
|
17
|
+
|
18
|
+
# @deprecated 6.0.0
|
19
|
+
FIELDS = ALLOWED_FIELDS
|
20
|
+
|
7
21
|
def initialize
|
8
22
|
@options = {}
|
9
23
|
end
|
10
24
|
|
11
25
|
def save(path, permission = nil)
|
12
|
-
contents =
|
26
|
+
contents = "---\n".dup
|
27
|
+
@options.each do |k,v|
|
28
|
+
next unless ALLOWED_FIELDS.include? k
|
29
|
+
case v
|
30
|
+
when Numeric
|
31
|
+
contents << "#{k}: #{v}\n"
|
32
|
+
when String
|
33
|
+
next if v.strip.empty?
|
34
|
+
contents << (k == 'running_from' || v.to_s.include?(' ') ?
|
35
|
+
"#{k}: \"#{v}\"\n" : "#{k}: #{v}\n")
|
36
|
+
end
|
37
|
+
end
|
13
38
|
if permission
|
14
39
|
File.write path, contents, mode: 'wb:UTF-8'
|
15
40
|
else
|
@@ -18,12 +43,21 @@ module Puma
|
|
18
43
|
end
|
19
44
|
|
20
45
|
def load(path)
|
21
|
-
|
46
|
+
File.read(path).lines.each do |line|
|
47
|
+
next if line.start_with? '#'
|
48
|
+
k,v = line.split ':', 2
|
49
|
+
next unless v && ALLOWED_FIELDS.include?(k)
|
50
|
+
v = v.strip
|
51
|
+
@options[k] =
|
52
|
+
case v
|
53
|
+
when /\A\d+\z/ then v.to_i
|
54
|
+
when /\A\d+\.\d+\z/ then v.to_f
|
55
|
+
else v.gsub(/\A"|"\z/, '')
|
56
|
+
end
|
57
|
+
end
|
22
58
|
end
|
23
59
|
|
24
|
-
|
25
|
-
|
26
|
-
FIELDS.each do |f|
|
60
|
+
ALLOWED_FIELDS.each do |f|
|
27
61
|
define_method f do
|
28
62
|
@options[f]
|
29
63
|
end
|
data/lib/puma/systemd.rb
CHANGED
File without changes
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -72,7 +72,7 @@ module Puma
|
|
72
72
|
attr_accessor :out_of_band_hook # @version 5.0.0
|
73
73
|
|
74
74
|
def self.clean_thread_locals
|
75
|
-
Thread.current.keys.each do |key| # rubocop: disable
|
75
|
+
Thread.current.keys.each do |key| # rubocop: disable Style/HashEachMethods
|
76
76
|
Thread.current[key] = nil unless key == :__recursive_key__
|
77
77
|
end
|
78
78
|
end
|
@@ -102,7 +102,7 @@ module Puma
|
|
102
102
|
@spawned += 1
|
103
103
|
|
104
104
|
th = Thread.new(@spawned) do |spawned|
|
105
|
-
Puma.set_thread_name '%s
|
105
|
+
Puma.set_thread_name '%s tp %03i' % [@name, spawned]
|
106
106
|
todo = @todo
|
107
107
|
block = @block
|
108
108
|
mutex = @mutex
|
data/lib/puma/util.rb
CHANGED
@@ -10,6 +10,13 @@ module Puma
|
|
10
10
|
IO.pipe
|
11
11
|
end
|
12
12
|
|
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
|
+
|
13
20
|
# Unescapes a URI escaped string with +encoding+. +encoding+ will be the
|
14
21
|
# target encoding of the string returned, and it defaults to UTF-8
|
15
22
|
if defined?(::Encoding)
|
data/lib/puma.rb
CHANGED
File without changes
|
data/lib/rack/handler/puma.rb
CHANGED
File without changes
|
data/tools/Dockerfile
CHANGED
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.
|
4
|
+
version: 5.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nio4r
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
|
-
rubygems_version: 3.2.
|
143
|
+
rubygems_version: 3.2.26
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for
|