puma 3.8.2 → 3.12.6
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 +5 -5
- data/History.md +153 -0
- data/README.md +140 -230
- data/docs/architecture.md +36 -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/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +112 -37
- data/ext/puma_http11/http11_parser.c +87 -85
- data/ext/puma_http11/http11_parser.rl +12 -10
- data/ext/puma_http11/mini_ssl.c +31 -5
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +13 -16
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -2
- data/lib/puma/app/status.rb +8 -0
- data/lib/puma/binder.rb +22 -17
- data/lib/puma/cli.rb +22 -7
- data/lib/puma/client.rb +41 -2
- data/lib/puma/cluster.rb +28 -7
- data/lib/puma/commonlogger.rb +2 -0
- data/lib/puma/configuration.rb +21 -14
- data/lib/puma/const.rb +17 -2
- data/lib/puma/control_cli.rb +16 -14
- data/lib/puma/convenient.rb +2 -0
- data/lib/puma/daemon_ext.rb +2 -0
- data/lib/puma/delegation.rb +2 -0
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +46 -9
- data/lib/puma/events.rb +3 -2
- data/lib/puma/io_buffer.rb +2 -0
- data/lib/puma/java_io_buffer.rb +2 -0
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher.rb +42 -20
- data/lib/puma/minissl.rb +67 -28
- data/lib/puma/null_io.rb +2 -0
- data/lib/puma/plugin/tmp_restart.rb +0 -1
- data/lib/puma/plugin.rb +2 -0
- data/lib/puma/rack/builder.rb +2 -1
- data/lib/puma/reactor.rb +137 -0
- data/lib/puma/runner.rb +16 -3
- data/lib/puma/server.rb +145 -29
- data/lib/puma/single.rb +14 -3
- data/lib/puma/state_file.rb +2 -0
- data/lib/puma/tcp_logger.rb +2 -0
- data/lib/puma/thread_pool.rb +55 -6
- data/lib/puma/util.rb +1 -0
- data/lib/puma.rb +8 -0
- data/lib/rack/handler/puma.rb +13 -2
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +2 -0
- data/tools/jungle/init.d/puma +2 -2
- data/tools/jungle/init.d/run-puma +1 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/trickletest.rb +1 -1
- metadata +21 -95
- data/.github/issue_template.md +0 -20
- data/Gemfile +0 -12
- data/Manifest.txt +0 -78
- data/Rakefile +0 -158
- data/Release.md +0 -9
- data/gemfiles/2.1-Gemfile +0 -12
- data/puma.gemspec +0 -52
- /data/{DEPLOYMENT.md → docs/deployment.md} +0 -0
data/lib/puma/control_cli.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'optparse'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
4
|
+
require_relative 'state_file'
|
5
|
+
require_relative 'const'
|
6
|
+
require_relative 'detect'
|
7
|
+
require_relative 'configuration'
|
6
8
|
require 'uri'
|
7
9
|
require 'socket'
|
8
10
|
|
9
11
|
module Puma
|
10
12
|
class ControlCLI
|
11
13
|
|
12
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
|
14
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
|
13
15
|
|
14
16
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
15
17
|
@state = nil
|
@@ -69,6 +71,7 @@ module Puma
|
|
69
71
|
end
|
70
72
|
|
71
73
|
opts.order!(argv) { |a| opts.terminate a }
|
74
|
+
opts.parse!
|
72
75
|
|
73
76
|
@command = argv.shift
|
74
77
|
|
@@ -128,7 +131,7 @@ module Puma
|
|
128
131
|
uri = URI.parse @control_url
|
129
132
|
|
130
133
|
# create server object by scheme
|
131
|
-
|
134
|
+
server = case uri.scheme
|
132
135
|
when "tcp"
|
133
136
|
TCPSocket.new uri.host, uri.port
|
134
137
|
when "unix"
|
@@ -146,9 +149,9 @@ module Puma
|
|
146
149
|
url = url + "?token=#{@control_auth_token}"
|
147
150
|
end
|
148
151
|
|
149
|
-
|
152
|
+
server << "GET #{url} HTTP/1.0\r\n\r\n"
|
150
153
|
|
151
|
-
unless data =
|
154
|
+
unless data = server.read
|
152
155
|
raise "Server closed connection before responding"
|
153
156
|
end
|
154
157
|
|
@@ -169,10 +172,10 @@ module Puma
|
|
169
172
|
end
|
170
173
|
|
171
174
|
message "Command #{@command} sent success"
|
172
|
-
message response.last if @command == "stats"
|
175
|
+
message response.last if @command == "stats" || @command == "gc-stats"
|
173
176
|
end
|
174
|
-
|
175
|
-
|
177
|
+
ensure
|
178
|
+
server.close if server && !server.closed?
|
176
179
|
end
|
177
180
|
|
178
181
|
def send_signal
|
@@ -204,7 +207,6 @@ module Puma
|
|
204
207
|
Process.kill "SIGUSR1", @pid
|
205
208
|
|
206
209
|
else
|
207
|
-
message "Puma is started"
|
208
210
|
return
|
209
211
|
end
|
210
212
|
|
@@ -220,7 +222,7 @@ module Puma
|
|
220
222
|
end
|
221
223
|
|
222
224
|
def run
|
223
|
-
start if @command == "start"
|
225
|
+
return start if @command == "start"
|
224
226
|
|
225
227
|
prepare_configuration
|
226
228
|
|
@@ -245,7 +247,7 @@ module Puma
|
|
245
247
|
run_args += ["-S", @state] if @state
|
246
248
|
run_args += ["-q"] if @quiet
|
247
249
|
run_args += ["--pidfile", @pidfile] if @pidfile
|
248
|
-
run_args += ["--control", @control_url] if @control_url
|
250
|
+
run_args += ["--control-url", @control_url] if @control_url
|
249
251
|
run_args += ["--control-token", @control_auth_token] if @control_auth_token
|
250
252
|
run_args += ["-C", @config_file] if @config_file
|
251
253
|
|
data/lib/puma/convenient.rb
CHANGED
data/lib/puma/daemon_ext.rb
CHANGED
data/lib/puma/delegation.rb
CHANGED
data/lib/puma/detect.rb
CHANGED
data/lib/puma/dsl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Puma
|
2
4
|
# The methods that are available for use inside the config file.
|
3
5
|
# These same methods are used in Puma cli and the rack handler
|
@@ -55,6 +57,14 @@ module Puma
|
|
55
57
|
@plugins.clear
|
56
58
|
end
|
57
59
|
|
60
|
+
def set_default_host(host)
|
61
|
+
@options[:default_host] = host
|
62
|
+
end
|
63
|
+
|
64
|
+
def default_host
|
65
|
+
@options[:default_host] || Configuration::DefaultTCPHost
|
66
|
+
end
|
67
|
+
|
58
68
|
def inject(&blk)
|
59
69
|
instance_eval(&blk)
|
60
70
|
end
|
@@ -110,18 +120,35 @@ module Puma
|
|
110
120
|
@options[:config_files] << file
|
111
121
|
end
|
112
122
|
|
113
|
-
#
|
114
|
-
# protocols.
|
123
|
+
# Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
|
124
|
+
# protocols. Use query parameters within the url to specify options.
|
125
|
+
#
|
126
|
+
# @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
|
127
|
+
#
|
128
|
+
# @example Explicitly the socket backlog depth (default is 1024)
|
129
|
+
# bind('unix:///var/run/puma.sock?backlog=2048')
|
130
|
+
#
|
131
|
+
# @example Set up ssl cert
|
132
|
+
# bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
|
115
133
|
#
|
134
|
+
# @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
|
135
|
+
# bind('tcp://0.0.0.0:9292?low_latency=true')
|
136
|
+
#
|
137
|
+
# @example Set socket permissions
|
138
|
+
# bind('unix:///var/run/puma.sock?umask=0111')
|
116
139
|
def bind(url)
|
117
140
|
@options[:binds] ||= []
|
118
141
|
@options[:binds] << url
|
119
142
|
end
|
120
143
|
|
144
|
+
def clear_binds!
|
145
|
+
@options[:binds] = []
|
146
|
+
end
|
147
|
+
|
121
148
|
# Define the TCP port to bind to. Use +bind+ for more advanced options.
|
122
149
|
#
|
123
150
|
def port(port, host=nil)
|
124
|
-
host ||=
|
151
|
+
host ||= default_host
|
125
152
|
bind "tcp://#{host}:#{port}"
|
126
153
|
end
|
127
154
|
|
@@ -129,7 +156,13 @@ module Puma
|
|
129
156
|
# them
|
130
157
|
#
|
131
158
|
def persistent_timeout(seconds)
|
132
|
-
@options[:persistent_timeout] = seconds
|
159
|
+
@options[:persistent_timeout] = Integer(seconds)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Define how long the tcp socket stays open, if no data has been received
|
163
|
+
#
|
164
|
+
def first_data_timeout(seconds)
|
165
|
+
@options[:first_data_timeout] = Integer(seconds)
|
133
166
|
end
|
134
167
|
|
135
168
|
# Work around leaky apps that leave garbage in Thread locals
|
@@ -146,7 +179,7 @@ module Puma
|
|
146
179
|
end
|
147
180
|
|
148
181
|
# When shutting down, drain the accept socket of pending
|
149
|
-
# connections and
|
182
|
+
# connections and process them. This loops over the accept
|
150
183
|
# socket until there are no more read events and then stops
|
151
184
|
# looking and waits for the requests to finish.
|
152
185
|
def drain_on_shutdown(which=true)
|
@@ -231,6 +264,10 @@ module Puma
|
|
231
264
|
@options[:mode] = :tcp
|
232
265
|
end
|
233
266
|
|
267
|
+
def early_hints(answer=true)
|
268
|
+
@options[:early_hints] = answer
|
269
|
+
end
|
270
|
+
|
234
271
|
# Redirect STDOUT and STDERR to files specified.
|
235
272
|
def stdout_redirect(stdout=nil, stderr=nil, append=false)
|
236
273
|
@options[:redirect_stdout] = stdout
|
@@ -397,17 +434,17 @@ module Puma
|
|
397
434
|
# that have not checked in within the given +timeout+.
|
398
435
|
# This mitigates hung processes. Default value is 60 seconds.
|
399
436
|
def worker_timeout(timeout)
|
400
|
-
@options[:worker_timeout] = timeout
|
437
|
+
@options[:worker_timeout] = Integer(timeout)
|
401
438
|
end
|
402
439
|
|
403
440
|
# *Cluster mode only* Set the timeout for workers to boot
|
404
441
|
def worker_boot_timeout(timeout)
|
405
|
-
@options[:worker_boot_timeout] = timeout
|
442
|
+
@options[:worker_boot_timeout] = Integer(timeout)
|
406
443
|
end
|
407
444
|
|
408
445
|
# *Cluster mode only* Set the timeout for worker shutdown
|
409
446
|
def worker_shutdown_timeout(timeout)
|
410
|
-
@options[:worker_shutdown_timeout] = timeout
|
447
|
+
@options[:worker_shutdown_timeout] = Integer(timeout)
|
411
448
|
end
|
412
449
|
|
413
450
|
# When set to true (the default), workers accept all requests
|
@@ -466,7 +503,7 @@ module Puma
|
|
466
503
|
when Hash
|
467
504
|
if hdr = val[:header]
|
468
505
|
@options[:remote_address] = :header
|
469
|
-
@options[:remote_address_header] = "HTTP_" + hdr.upcase.
|
506
|
+
@options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
|
470
507
|
else
|
471
508
|
raise "Invalid value for set_remote_address - #{val.inspect}"
|
472
509
|
end
|
data/lib/puma/events.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puma/const'
|
2
4
|
require "puma/null_io"
|
3
5
|
require 'stringio'
|
@@ -91,8 +93,7 @@ module Puma
|
|
91
93
|
# parsing exception.
|
92
94
|
#
|
93
95
|
def parse_error(server, env, error)
|
94
|
-
@stderr.puts "#{Time.now}: HTTP parse error, malformed request (#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}): #{error.inspect}"
|
95
|
-
@stderr.puts "#{Time.now}: ENV: #{env.inspect}\n---\n"
|
96
|
+
@stderr.puts "#{Time.now}: HTTP parse error, malformed request (#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}): #{error.inspect}\n---\n"
|
96
97
|
end
|
97
98
|
|
98
99
|
# An SSL error has occurred.
|
data/lib/puma/io_buffer.rb
CHANGED
data/lib/puma/java_io_buffer.rb
CHANGED
data/lib/puma/jruby_restart.rb
CHANGED
data/lib/puma/launcher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puma/events'
|
2
4
|
require 'puma/detect'
|
3
5
|
|
@@ -40,7 +42,7 @@ module Puma
|
|
40
42
|
# [200, {}, ["hello world"]]
|
41
43
|
# end
|
42
44
|
# end
|
43
|
-
# Puma::Launcher.new(conf,
|
45
|
+
# Puma::Launcher.new(conf, events: Puma::Events.stdio).run
|
44
46
|
def initialize(conf, launcher_args={})
|
45
47
|
@runner = nil
|
46
48
|
@events = launcher_args[:events] || Events::DEFAULT
|
@@ -63,8 +65,8 @@ module Puma
|
|
63
65
|
|
64
66
|
generate_restart_data
|
65
67
|
|
66
|
-
if clustered? &&
|
67
|
-
unsupported
|
68
|
+
if clustered? && !Process.respond_to?(:fork)
|
69
|
+
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
68
70
|
end
|
69
71
|
|
70
72
|
if @options[:daemon] && Puma.windows?
|
@@ -86,6 +88,7 @@ module Puma
|
|
86
88
|
else
|
87
89
|
@runner = Single.new(self, @events)
|
88
90
|
end
|
91
|
+
Puma.stats_object = @runner
|
89
92
|
|
90
93
|
@status = :run
|
91
94
|
end
|
@@ -163,6 +166,17 @@ module Puma
|
|
163
166
|
|
164
167
|
# Run the server. This blocks until the server is stopped
|
165
168
|
def run
|
169
|
+
previous_env =
|
170
|
+
if defined?(Bundler)
|
171
|
+
env = Bundler::ORIGINAL_ENV.dup
|
172
|
+
# add -rbundler/setup so we load from Gemfile when restarting
|
173
|
+
bundle = "-rbundler/setup"
|
174
|
+
env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
|
175
|
+
env
|
176
|
+
else
|
177
|
+
ENV.to_h
|
178
|
+
end
|
179
|
+
|
166
180
|
@config.clamp
|
167
181
|
|
168
182
|
@config.plugins.fire_starts self
|
@@ -178,6 +192,7 @@ module Puma
|
|
178
192
|
graceful_stop
|
179
193
|
when :restart
|
180
194
|
log "* Restarting..."
|
195
|
+
ENV.replace(previous_env)
|
181
196
|
@runner.before_restart
|
182
197
|
restart!
|
183
198
|
when :exit
|
@@ -222,8 +237,8 @@ module Puma
|
|
222
237
|
else
|
223
238
|
redirects = {:close_others => true}
|
224
239
|
@binder.listeners.each_with_index do |(l, io), i|
|
225
|
-
|
226
|
-
|
240
|
+
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
241
|
+
redirects[io.to_i] = io.to_i
|
227
242
|
end
|
228
243
|
|
229
244
|
argv = restart_args
|
@@ -286,8 +301,8 @@ module Puma
|
|
286
301
|
end
|
287
302
|
|
288
303
|
def title
|
289
|
-
buffer
|
290
|
-
buffer
|
304
|
+
buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
|
305
|
+
buffer += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
291
306
|
buffer
|
292
307
|
end
|
293
308
|
|
@@ -337,8 +352,6 @@ module Puma
|
|
337
352
|
|
338
353
|
@restart_dir ||= Dir.pwd
|
339
354
|
|
340
|
-
require 'rubygems'
|
341
|
-
|
342
355
|
# if $0 is a file in the current directory, then restart
|
343
356
|
# it the same, otherwise add -S on there because it was
|
344
357
|
# picked up in PATH.
|
@@ -349,9 +362,10 @@ module Puma
|
|
349
362
|
arg0 = [Gem.ruby, "-S", $0]
|
350
363
|
end
|
351
364
|
|
352
|
-
# Detect and reinject -Ilib from the command line
|
365
|
+
# Detect and reinject -Ilib from the command line, used for testing without bundler
|
366
|
+
# cruby has an expanded path, jruby has just "lib"
|
353
367
|
lib = File.expand_path "lib"
|
354
|
-
arg0[1,0] = ["-I", lib] if
|
368
|
+
arg0[1,0] = ["-I", lib] if [lib, "lib"].include?($LOAD_PATH[0])
|
355
369
|
|
356
370
|
if defined? Puma::WILD_ARGS
|
357
371
|
@restart_argv = arg0 + Puma::WILD_ARGS + @original_argv
|
@@ -381,12 +395,28 @@ module Puma
|
|
381
395
|
|
382
396
|
begin
|
383
397
|
Signal.trap "SIGTERM" do
|
384
|
-
|
398
|
+
graceful_stop
|
399
|
+
|
400
|
+
raise SignalException, "SIGTERM"
|
385
401
|
end
|
386
402
|
rescue Exception
|
387
403
|
log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
|
388
404
|
end
|
389
405
|
|
406
|
+
begin
|
407
|
+
Signal.trap "SIGINT" do
|
408
|
+
if Puma.jruby?
|
409
|
+
@status = :exit
|
410
|
+
graceful_stop
|
411
|
+
exit
|
412
|
+
end
|
413
|
+
|
414
|
+
stop
|
415
|
+
end
|
416
|
+
rescue Exception
|
417
|
+
log "*** SIGINT not implemented, signal based gracefully stopping unavailable!"
|
418
|
+
end
|
419
|
+
|
390
420
|
begin
|
391
421
|
Signal.trap "SIGHUP" do
|
392
422
|
if @runner.redirected_io?
|
@@ -398,14 +428,6 @@ module Puma
|
|
398
428
|
rescue Exception
|
399
429
|
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
400
430
|
end
|
401
|
-
|
402
|
-
if Puma.jruby?
|
403
|
-
Signal.trap("INT") do
|
404
|
-
@status = :exit
|
405
|
-
graceful_stop
|
406
|
-
exit
|
407
|
-
end
|
408
|
-
end
|
409
431
|
end
|
410
432
|
end
|
411
433
|
end
|
data/lib/puma/minissl.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'io/wait'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
1
8
|
module Puma
|
2
9
|
module MiniSSL
|
3
10
|
class Socket
|
@@ -11,6 +18,10 @@ module Puma
|
|
11
18
|
@socket
|
12
19
|
end
|
13
20
|
|
21
|
+
def closed?
|
22
|
+
@socket.closed?
|
23
|
+
end
|
24
|
+
|
14
25
|
def readpartial(size)
|
15
26
|
while true
|
16
27
|
output = @engine.read
|
@@ -36,12 +47,29 @@ module Puma
|
|
36
47
|
output
|
37
48
|
end
|
38
49
|
|
39
|
-
def read_nonblock(size)
|
50
|
+
def read_nonblock(size, *_)
|
51
|
+
# *_ is to deal with keyword args that were added
|
52
|
+
# at some point (and being used in the wild)
|
40
53
|
while true
|
41
54
|
output = engine_read_all
|
42
55
|
return output if output
|
43
56
|
|
44
|
-
|
57
|
+
begin
|
58
|
+
data = @socket.read_nonblock(size, exception: false)
|
59
|
+
if data == :wait_readable || data == :wait_writable
|
60
|
+
if @socket.to_io.respond_to?(data)
|
61
|
+
@socket.to_io.__send__(data)
|
62
|
+
elsif data == :wait_readable
|
63
|
+
IO.select([@socket.to_io])
|
64
|
+
else
|
65
|
+
IO.select(nil, [@socket.to_io])
|
66
|
+
end
|
67
|
+
elsif !data
|
68
|
+
return nil
|
69
|
+
else
|
70
|
+
break
|
71
|
+
end
|
72
|
+
end while true
|
45
73
|
|
46
74
|
@engine.inject(data)
|
47
75
|
output = engine_read_all
|
@@ -55,6 +83,8 @@ module Puma
|
|
55
83
|
end
|
56
84
|
|
57
85
|
def write(data)
|
86
|
+
return 0 if data.empty?
|
87
|
+
|
58
88
|
need = data.bytesize
|
59
89
|
|
60
90
|
while true
|
@@ -77,39 +107,46 @@ module Puma
|
|
77
107
|
alias_method :syswrite, :write
|
78
108
|
alias_method :<<, :write
|
79
109
|
|
110
|
+
# This is a temporary fix to deal with websockets code using
|
111
|
+
# write_nonblock. The problem with implementing it properly
|
112
|
+
# is that it means we'd have to have the ability to rewind
|
113
|
+
# an engine because after we write+extract, the socket
|
114
|
+
# write_nonblock call might raise an exception and later
|
115
|
+
# code would pass the same data in, but the engine would think
|
116
|
+
# it had already written the data in. So for the time being
|
117
|
+
# (and since write blocking is quite rare), go ahead and actually
|
118
|
+
# block in write_nonblock.
|
119
|
+
def write_nonblock(data, *_)
|
120
|
+
write data
|
121
|
+
end
|
122
|
+
|
80
123
|
def flush
|
81
124
|
@socket.flush
|
82
125
|
end
|
83
126
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
return unless IO.select([@socket], nil, nil, 1)
|
93
|
-
begin
|
94
|
-
read_nonblock(1024)
|
95
|
-
rescue Errno::EAGAIN
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
done = @engine.shutdown
|
100
|
-
|
101
|
-
while true
|
102
|
-
enc = @engine.extract
|
103
|
-
@socket.write enc
|
104
|
-
|
105
|
-
notify = @socket.sysread(1024)
|
127
|
+
def read_and_drop(timeout = 1)
|
128
|
+
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
129
|
+
return :eof unless read_nonblock(1024)
|
130
|
+
:drop
|
131
|
+
rescue Errno::EAGAIN
|
132
|
+
# do nothing
|
133
|
+
:eagain
|
134
|
+
end
|
106
135
|
|
107
|
-
|
108
|
-
|
136
|
+
def should_drop_bytes?
|
137
|
+
@engine.init? || !@engine.shutdown
|
138
|
+
end
|
109
139
|
|
110
|
-
|
140
|
+
def close
|
141
|
+
begin
|
142
|
+
# Read any drop any partially initialized sockets and any received bytes during shutdown.
|
143
|
+
# Don't let this socket hold this loop forever.
|
144
|
+
# If it can't send more packets within 1s, then give up.
|
145
|
+
while should_drop_bytes?
|
146
|
+
return if [:timeout, :eof].include?(read_and_drop(1))
|
111
147
|
end
|
112
148
|
rescue IOError, SystemCallError
|
149
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
113
150
|
# nothing
|
114
151
|
ensure
|
115
152
|
@socket.close
|
@@ -145,6 +182,7 @@ module Puma
|
|
145
182
|
# jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
|
146
183
|
attr_reader :keystore
|
147
184
|
attr_accessor :keystore_pass
|
185
|
+
attr_accessor :ssl_cipher_list
|
148
186
|
|
149
187
|
def keystore=(keystore)
|
150
188
|
raise ArgumentError, "No such keystore file '#{keystore}'" unless File.exist? keystore
|
@@ -160,6 +198,7 @@ module Puma
|
|
160
198
|
attr_reader :key
|
161
199
|
attr_reader :cert
|
162
200
|
attr_reader :ca
|
201
|
+
attr_accessor :ssl_cipher_filter
|
163
202
|
|
164
203
|
def key=(key)
|
165
204
|
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
|
@@ -214,7 +253,7 @@ module Puma
|
|
214
253
|
end
|
215
254
|
|
216
255
|
def close
|
217
|
-
@socket.close
|
256
|
+
@socket.close unless @socket.closed? # closed? call is for Windows
|
218
257
|
end
|
219
258
|
end
|
220
259
|
end
|
data/lib/puma/null_io.rb
CHANGED
data/lib/puma/plugin.rb
CHANGED
data/lib/puma/rack/builder.rb
CHANGED
@@ -110,7 +110,8 @@ module Puma::Rack
|
|
110
110
|
|
111
111
|
has_options = false
|
112
112
|
server.valid_options.each do |name, description|
|
113
|
-
next if name.to_s
|
113
|
+
next if name.to_s =~ /^(Host|Port)[^a-zA-Z]/ # ignore handler's host and port options, we do our own.
|
114
|
+
|
114
115
|
info << " -O %-21s %s" % [name, description]
|
115
116
|
has_options = true
|
116
117
|
end
|