puma 5.3.2 → 5.6.4
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 +148 -8
- data/LICENSE +0 -0
- data/README.md +47 -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 -67
- 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 +64 -67
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +28 -5
- 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 +69 -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 +4 -4
- data/lib/puma/binder.rb +50 -5
- data/lib/puma/cli.rb +14 -4
- data/lib/puma/client.rb +104 -20
- data/lib/puma/cluster/worker.rb +8 -18
- data/lib/puma/cluster/worker_handle.rb +4 -0
- data/lib/puma/cluster.rb +30 -24
- data/lib/puma/commonlogger.rb +0 -0
- data/lib/puma/configuration.rb +4 -1
- data/lib/puma/const.rb +9 -8
- data/lib/puma/control_cli.rb +1 -1
- data/lib/puma/detect.rb +8 -2
- data/lib/puma/dsl.rb +105 -11
- 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.rb → json_serialization.rb} +1 -1
- data/lib/puma/launcher.rb +4 -1
- data/lib/puma/minissl/context_builder.rb +8 -6
- data/lib/puma/minissl.rb +24 -23
- data/lib/puma/null_io.rb +0 -0
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +2 -2
- data/lib/puma/queue_close.rb +0 -0
- data/lib/puma/rack/builder.rb +1 -1
- 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 +14 -9
- data/lib/puma/runner.rb +22 -8
- data/lib/puma/server.rb +35 -29
- 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 +7 -5
- data/lib/puma/util.rb +8 -1
- data/lib/puma.rb +2 -2
- data/lib/rack/handler/puma.rb +0 -0
- data/tools/Dockerfile +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +7 -7
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".
|
@@ -381,6 +383,13 @@ module Puma
|
|
381
383
|
@options[:rackup] ||= path.to_s
|
382
384
|
end
|
383
385
|
|
386
|
+
# Allows setting `env['rack.url_scheme']`.
|
387
|
+
# Only necessary if X-Forwarded-Proto is not being set by your proxy
|
388
|
+
# Normal values are 'http' or 'https'.
|
389
|
+
def rack_url_scheme(scheme=nil)
|
390
|
+
@options[:rack_url_scheme] = scheme
|
391
|
+
end
|
392
|
+
|
384
393
|
def early_hints(answer=true)
|
385
394
|
@options[:early_hints] = answer
|
386
395
|
end
|
@@ -429,8 +438,15 @@ module Puma
|
|
429
438
|
@options[:max_threads] = max
|
430
439
|
end
|
431
440
|
|
432
|
-
# Instead of
|
433
|
-
#
|
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.
|
434
450
|
#
|
435
451
|
# @example
|
436
452
|
# ssl_bind '127.0.0.1', '9292', {
|
@@ -440,14 +456,25 @@ module Puma
|
|
440
456
|
# verify_mode: verify_mode, # default 'none'
|
441
457
|
# verification_flags: flags, # optional, not supported by JRuby
|
442
458
|
# }
|
443
|
-
#
|
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+
|
444
470
|
# ssl_bind '127.0.0.1', '9292', {
|
445
471
|
# keystore: path_to_keystore,
|
446
472
|
# keystore_pass: password,
|
447
473
|
# ssl_cipher_list: cipher_list, # optional
|
448
474
|
# verify_mode: verify_mode # default 'none'
|
449
475
|
# }
|
450
|
-
def ssl_bind(host, port, opts)
|
476
|
+
def ssl_bind(host, port, opts = {})
|
477
|
+
add_pem_values_to_options_store(opts)
|
451
478
|
bind self.class.ssl_bind_str(host, port, opts)
|
452
479
|
end
|
453
480
|
|
@@ -578,7 +605,7 @@ module Puma
|
|
578
605
|
# end
|
579
606
|
def after_worker_fork(&block)
|
580
607
|
@options[:after_worker_fork] ||= []
|
581
|
-
@options[:after_worker_fork]
|
608
|
+
@options[:after_worker_fork] << block
|
582
609
|
end
|
583
610
|
|
584
611
|
alias_method :after_worker_boot, :after_worker_fork
|
@@ -720,6 +747,19 @@ module Puma
|
|
720
747
|
@options[:tag] = string.to_s
|
721
748
|
end
|
722
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
|
+
|
723
763
|
# Verifies that all workers have checked in to the master process within
|
724
764
|
# the given timeout. If not the worker process will be restarted. This is
|
725
765
|
# not a request timeout, it is to protect against a hung or dead process.
|
@@ -734,7 +774,7 @@ module Puma
|
|
734
774
|
#
|
735
775
|
def worker_timeout(timeout)
|
736
776
|
timeout = Integer(timeout)
|
737
|
-
min =
|
777
|
+
min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
|
738
778
|
|
739
779
|
if timeout <= min
|
740
780
|
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
@@ -766,6 +806,30 @@ module Puma
|
|
766
806
|
@options[:worker_shutdown_timeout] = Integer(timeout)
|
767
807
|
end
|
768
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
|
+
|
769
833
|
# When set to true (the default), workers accept all requests
|
770
834
|
# and queue them before passing them to the handlers.
|
771
835
|
# When set to false, each worker process accepts exactly as
|
@@ -811,7 +875,7 @@ module Puma
|
|
811
875
|
# a kernel syscall is required which for very fast rack handlers
|
812
876
|
# slows down the handling significantly.
|
813
877
|
#
|
814
|
-
# There are
|
878
|
+
# There are 5 possible values:
|
815
879
|
#
|
816
880
|
# 1. **:socket** (the default) - read the peername from the socket using the
|
817
881
|
# syscall. This is the normal behavior.
|
@@ -821,7 +885,10 @@ module Puma
|
|
821
885
|
# `set_remote_address header: "X-Real-IP"`.
|
822
886
|
# Only the first word (as separated by spaces or comma) is used, allowing
|
823
887
|
# headers such as X-Forwarded-For to be used as well.
|
824
|
-
# 4.
|
888
|
+
# 4. **proxy_protocol: :v1**- set the remote address to the value read from the
|
889
|
+
# HAproxy PROXY protocol, version 1. If the request does not have the PROXY
|
890
|
+
# protocol attached to it, will fall back to :socket
|
891
|
+
# 5. **\<Any string\>** - this allows you to hardcode remote address to any value
|
825
892
|
# you wish. Because Puma never uses this field anyway, it's format is
|
826
893
|
# entirely in your hands.
|
827
894
|
#
|
@@ -839,6 +906,13 @@ module Puma
|
|
839
906
|
if hdr = val[:header]
|
840
907
|
@options[:remote_address] = :header
|
841
908
|
@options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
|
909
|
+
elsif protocol_version = val[:proxy_protocol]
|
910
|
+
@options[:remote_address] = :proxy_protocol
|
911
|
+
protocol_version = protocol_version.downcase.to_sym
|
912
|
+
unless [:v1].include?(protocol_version)
|
913
|
+
raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
|
914
|
+
end
|
915
|
+
@options[:remote_address_proxy_protocol] = protocol_version
|
842
916
|
else
|
843
917
|
raise "Invalid value for set_remote_address - #{val.inspect}"
|
844
918
|
end
|
@@ -910,5 +984,25 @@ module Puma
|
|
910
984
|
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
|
911
985
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
912
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
|
913
1007
|
end
|
914
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
|
@@ -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
|
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
|
|
@@ -319,10 +320,12 @@ module Puma
|
|
319
320
|
log '* Pruning Bundler environment'
|
320
321
|
home = ENV['GEM_HOME']
|
321
322
|
bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
|
323
|
+
bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
|
322
324
|
with_unbundled_env do
|
323
325
|
ENV['GEM_HOME'] = home
|
324
326
|
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
325
327
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
328
|
+
ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
|
326
329
|
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
|
327
330
|
# Ruby 2.0+ defaults to true which breaks socket activation
|
328
331
|
args += [{:close_others => false}]
|
@@ -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
@@ -161,30 +161,15 @@ module Puma
|
|
161
161
|
@socket.flush
|
162
162
|
end
|
163
163
|
|
164
|
-
def read_and_drop(timeout = 1)
|
165
|
-
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
166
|
-
case @socket.read_nonblock(1024, exception: false)
|
167
|
-
when nil
|
168
|
-
:eof
|
169
|
-
when :wait_readable
|
170
|
-
:eagain
|
171
|
-
else
|
172
|
-
:drop
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def should_drop_bytes?
|
177
|
-
@engine.init? || !@engine.shutdown
|
178
|
-
end
|
179
|
-
|
180
164
|
def close
|
181
165
|
begin
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
166
|
+
unless @engine.shutdown
|
167
|
+
while alert_data = @engine.extract
|
168
|
+
@socket.write alert_data
|
169
|
+
end
|
170
|
+
end
|
186
171
|
rescue IOError, SystemCallError
|
187
|
-
|
172
|
+
Puma::Util.purge_interrupt_queue
|
188
173
|
# nothing
|
189
174
|
ensure
|
190
175
|
@socket.close
|
@@ -223,6 +208,10 @@ module Puma
|
|
223
208
|
def initialize
|
224
209
|
@no_tlsv1 = false
|
225
210
|
@no_tlsv1_1 = false
|
211
|
+
@key = nil
|
212
|
+
@cert = nil
|
213
|
+
@key_pem = nil
|
214
|
+
@cert_pem = nil
|
226
215
|
end
|
227
216
|
|
228
217
|
if IS_JRUBY
|
@@ -245,6 +234,8 @@ module Puma
|
|
245
234
|
attr_reader :key
|
246
235
|
attr_reader :cert
|
247
236
|
attr_reader :ca
|
237
|
+
attr_reader :cert_pem
|
238
|
+
attr_reader :key_pem
|
248
239
|
attr_accessor :ssl_cipher_filter
|
249
240
|
attr_accessor :verification_flags
|
250
241
|
|
@@ -263,9 +254,19 @@ module Puma
|
|
263
254
|
@ca = ca
|
264
255
|
end
|
265
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
|
+
|
266
267
|
def check
|
267
|
-
raise "Key not configured"
|
268
|
-
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?
|
269
270
|
end
|
270
271
|
end
|
271
272
|
|
data/lib/puma/null_io.rb
CHANGED
File without changes
|
File without changes
|
data/lib/puma/plugin.rb
CHANGED
@@ -64,7 +64,7 @@ module Puma
|
|
64
64
|
def fire_background
|
65
65
|
@background.each_with_index do |b, i|
|
66
66
|
Thread.new do
|
67
|
-
Puma.set_thread_name "
|
67
|
+
Puma.set_thread_name "plgn bg #{i}"
|
68
68
|
b.call
|
69
69
|
end
|
70
70
|
end
|
@@ -91,7 +91,7 @@ module Puma
|
|
91
91
|
path = ary.first[CALLER_FILE]
|
92
92
|
|
93
93
|
m = %r!puma/plugin/([^/]*)\.rb$!.match(path)
|
94
|
-
|
94
|
+
m[1]
|
95
95
|
end
|
96
96
|
|
97
97
|
def self.create(&blk)
|
data/lib/puma/queue_close.rb
CHANGED
File without changes
|
data/lib/puma/rack/builder.rb
CHANGED
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
@@ -51,7 +51,7 @@ module Puma
|
|
51
51
|
head = env[REQUEST_METHOD] == HEAD
|
52
52
|
|
53
53
|
env[RACK_INPUT] = body
|
54
|
-
env[RACK_URL_SCHEME]
|
54
|
+
env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
|
55
55
|
|
56
56
|
if @early_hints
|
57
57
|
env[EARLY_HINTS] = lambda { |headers|
|
@@ -167,16 +167,21 @@ module Puma
|
|
167
167
|
end
|
168
168
|
|
169
169
|
ensure
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
170
|
+
begin
|
171
|
+
uncork_socket io
|
172
|
+
|
173
|
+
body.close
|
174
|
+
client.tempfile.unlink if client.tempfile
|
175
|
+
ensure
|
176
|
+
# Whatever happens, we MUST call `close` on the response body.
|
177
|
+
# Otherwise Rack::BodyProxy callbacks may not fire and lead to various state leaks
|
178
|
+
res_body.close if res_body.respond_to? :close
|
179
|
+
end
|
175
180
|
|
176
181
|
after_reply.each { |o| o.call }
|
177
182
|
end
|
178
183
|
|
179
|
-
|
184
|
+
res_info[:keep_alive]
|
180
185
|
end
|
181
186
|
|
182
187
|
# @param env [Hash] see Puma::Client#env, from request
|
@@ -201,7 +206,7 @@ module Puma
|
|
201
206
|
begin
|
202
207
|
n = io.syswrite str
|
203
208
|
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
204
|
-
|
209
|
+
unless io.wait_writable WRITE_TIMEOUT
|
205
210
|
raise ConnectionError, "Socket timeout writing data"
|
206
211
|
end
|
207
212
|
|
@@ -419,7 +424,7 @@ module Puma
|
|
419
424
|
# of concurrent connections exceeds the size of the threadpool.
|
420
425
|
res_info[:keep_alive] &&= requests < @max_fast_inline ||
|
421
426
|
@thread_pool.busy_threads < @max_threads ||
|
422
|
-
!
|
427
|
+
!client.listener.to_io.wait_readable(0)
|
423
428
|
|
424
429
|
res_info[:response_hijack] = nil
|
425
430
|
|
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
|