puma 4.1.1 → 4.3.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 +55 -7
- data/README.md +8 -37
- data/docs/plugins.md +20 -10
- data/docs/tcp_mode.md +96 -0
- data/ext/puma_http11/extconf.rb +5 -0
- data/ext/puma_http11/http11_parser.c +37 -62
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser_common.rl +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11.java +106 -114
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +91 -106
- data/ext/puma_http11/puma_http11.c +2 -0
- data/lib/puma.rb +6 -0
- data/lib/puma/app/status.rb +29 -28
- data/lib/puma/binder.rb +38 -70
- data/lib/puma/cli.rb +4 -0
- data/lib/puma/client.rb +194 -206
- data/lib/puma/cluster.rb +13 -12
- data/lib/puma/const.rb +22 -18
- data/lib/puma/control_cli.rb +20 -3
- data/lib/puma/dsl.rb +19 -1
- data/lib/puma/launcher.rb +87 -46
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/plugin.rb +5 -2
- data/lib/puma/reactor.rb +7 -5
- data/lib/puma/runner.rb +10 -3
- data/lib/puma/server.rb +29 -12
- data/lib/puma/thread_pool.rb +10 -32
- data/lib/rack/handler/puma.rb +0 -2
- data/tools/docker/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +6 -5
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
@@ -0,0 +1,76 @@
|
|
1
|
+
module Puma
|
2
|
+
module MiniSSL
|
3
|
+
class ContextBuilder
|
4
|
+
def initialize(params, events)
|
5
|
+
require 'puma/minissl'
|
6
|
+
MiniSSL.check
|
7
|
+
|
8
|
+
@params = params
|
9
|
+
@events = events
|
10
|
+
end
|
11
|
+
|
12
|
+
def context
|
13
|
+
ctx = MiniSSL::Context.new
|
14
|
+
|
15
|
+
if defined?(JRUBY_VERSION)
|
16
|
+
unless params['keystore']
|
17
|
+
events.error "Please specify the Java keystore via 'keystore='"
|
18
|
+
end
|
19
|
+
|
20
|
+
ctx.keystore = params['keystore']
|
21
|
+
|
22
|
+
unless params['keystore-pass']
|
23
|
+
events.error "Please specify the Java keystore password via 'keystore-pass='"
|
24
|
+
end
|
25
|
+
|
26
|
+
ctx.keystore_pass = params['keystore-pass']
|
27
|
+
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
28
|
+
else
|
29
|
+
unless params['key']
|
30
|
+
events.error "Please specify the SSL key via 'key='"
|
31
|
+
end
|
32
|
+
|
33
|
+
ctx.key = params['key']
|
34
|
+
|
35
|
+
unless params['cert']
|
36
|
+
events.error "Please specify the SSL cert via 'cert='"
|
37
|
+
end
|
38
|
+
|
39
|
+
ctx.cert = params['cert']
|
40
|
+
|
41
|
+
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
42
|
+
unless params['ca']
|
43
|
+
events.error "Please specify the SSL ca via 'ca='"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
ctx.ca = params['ca'] if params['ca']
|
48
|
+
ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
|
49
|
+
end
|
50
|
+
|
51
|
+
ctx.no_tlsv1 = true if params['no_tlsv1'] == 'true'
|
52
|
+
ctx.no_tlsv1_1 = true if params['no_tlsv1_1'] == 'true'
|
53
|
+
|
54
|
+
if params['verify_mode']
|
55
|
+
ctx.verify_mode = case params['verify_mode']
|
56
|
+
when "peer"
|
57
|
+
MiniSSL::VERIFY_PEER
|
58
|
+
when "force_peer"
|
59
|
+
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
60
|
+
when "none"
|
61
|
+
MiniSSL::VERIFY_NONE
|
62
|
+
else
|
63
|
+
events.error "Please specify a valid verify_mode="
|
64
|
+
MiniSSL::VERIFY_NONE
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
ctx
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
attr_reader :params, :events
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/puma/plugin.rb
CHANGED
data/lib/puma/reactor.rb
CHANGED
@@ -225,7 +225,7 @@ module Puma
|
|
225
225
|
# will be flooding them with errors when persistent connections
|
226
226
|
# are closed.
|
227
227
|
rescue ConnectionError
|
228
|
-
c.
|
228
|
+
c.write_error(500)
|
229
229
|
c.close
|
230
230
|
|
231
231
|
clear_monitor mon
|
@@ -237,7 +237,8 @@ module Puma
|
|
237
237
|
ssl_socket = c.io
|
238
238
|
begin
|
239
239
|
addr = ssl_socket.peeraddr.last
|
240
|
-
|
240
|
+
# EINVAL can happen when browser closes socket w/security exception
|
241
|
+
rescue IOError, Errno::EINVAL
|
241
242
|
addr = "<unknown>"
|
242
243
|
end
|
243
244
|
|
@@ -252,7 +253,7 @@ module Puma
|
|
252
253
|
rescue HttpParserError => e
|
253
254
|
@server.lowlevel_error(e, c.env)
|
254
255
|
|
255
|
-
c.
|
256
|
+
c.write_error(400)
|
256
257
|
c.close
|
257
258
|
|
258
259
|
clear_monitor mon
|
@@ -261,7 +262,7 @@ module Puma
|
|
261
262
|
rescue StandardError => e
|
262
263
|
@server.lowlevel_error(e, c.env)
|
263
264
|
|
264
|
-
c.
|
265
|
+
c.write_error(500)
|
265
266
|
c.close
|
266
267
|
|
267
268
|
clear_monitor mon
|
@@ -277,7 +278,7 @@ module Puma
|
|
277
278
|
while @timeouts.first.value.timeout_at < now
|
278
279
|
mon = @timeouts.shift
|
279
280
|
c = mon.value
|
280
|
-
c.
|
281
|
+
c.write_error(408) if c.in_data_phase
|
281
282
|
c.close
|
282
283
|
|
283
284
|
clear_monitor mon
|
@@ -307,6 +308,7 @@ module Puma
|
|
307
308
|
|
308
309
|
def run_in_thread
|
309
310
|
@thread = Thread.new do
|
311
|
+
Puma.set_thread_name "reactor"
|
310
312
|
begin
|
311
313
|
run_internal
|
312
314
|
rescue StandardError => e
|
data/lib/puma/runner.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'puma/server'
|
4
4
|
require 'puma/const'
|
5
|
+
require 'puma/minissl/context_builder'
|
5
6
|
|
6
7
|
module Puma
|
7
8
|
# Generic class that is used by `Puma::Cluster` and `Puma::Single` to
|
@@ -53,17 +54,23 @@ module Puma
|
|
53
54
|
|
54
55
|
uri = URI.parse str
|
55
56
|
|
56
|
-
app = Puma::App::Status.new @launcher
|
57
|
-
|
58
57
|
if token = @options[:control_auth_token]
|
59
|
-
|
58
|
+
token = nil if token.empty? || token == 'none'
|
60
59
|
end
|
61
60
|
|
61
|
+
app = Puma::App::Status.new @launcher, token
|
62
|
+
|
62
63
|
control = Puma::Server.new app, @launcher.events
|
63
64
|
control.min_threads = 0
|
64
65
|
control.max_threads = 1
|
65
66
|
|
66
67
|
case uri.scheme
|
68
|
+
when "ssl"
|
69
|
+
log "* Starting control server on #{str}"
|
70
|
+
params = Util.parse_query uri.query
|
71
|
+
ctx = MiniSSL::ContextBuilder.new(params, @events).context
|
72
|
+
|
73
|
+
control.add_ssl_listener uri.host, uri.port, ctx
|
67
74
|
when "tcp"
|
68
75
|
log "* Starting control server on #{str}"
|
69
76
|
control.add_tcp_listener uri.host, uri.port
|
data/lib/puma/server.rb
CHANGED
@@ -9,13 +9,13 @@ require 'puma/null_io'
|
|
9
9
|
require 'puma/reactor'
|
10
10
|
require 'puma/client'
|
11
11
|
require 'puma/binder'
|
12
|
-
require 'puma/delegation'
|
13
12
|
require 'puma/accept_nonblock'
|
14
13
|
require 'puma/util'
|
15
14
|
|
16
15
|
require 'puma/puma_http11'
|
17
16
|
|
18
17
|
require 'socket'
|
18
|
+
require 'forwardable'
|
19
19
|
|
20
20
|
module Puma
|
21
21
|
|
@@ -32,7 +32,7 @@ module Puma
|
|
32
32
|
class Server
|
33
33
|
|
34
34
|
include Puma::Const
|
35
|
-
extend
|
35
|
+
extend Forwardable
|
36
36
|
|
37
37
|
attr_reader :thread
|
38
38
|
attr_reader :events
|
@@ -89,10 +89,7 @@ module Puma
|
|
89
89
|
|
90
90
|
attr_accessor :binder, :leak_stack_on_error, :early_hints
|
91
91
|
|
92
|
-
|
93
|
-
forward :add_ssl_listener, :@binder
|
94
|
-
forward :add_unix_listener, :@binder
|
95
|
-
forward :connected_port, :@binder
|
92
|
+
def_delegators :@binder, :add_tcp_listener, :add_ssl_listener, :add_unix_listener, :connected_port
|
96
93
|
|
97
94
|
def inherit_binder(bind)
|
98
95
|
@binder = bind
|
@@ -207,7 +204,10 @@ module Puma
|
|
207
204
|
@events.fire :state, :running
|
208
205
|
|
209
206
|
if background
|
210
|
-
@thread = Thread.new
|
207
|
+
@thread = Thread.new do
|
208
|
+
Puma.set_thread_name "server"
|
209
|
+
handle_servers_lopez_mode
|
210
|
+
end
|
211
211
|
return @thread
|
212
212
|
else
|
213
213
|
handle_servers_lopez_mode
|
@@ -317,7 +317,7 @@ module Puma
|
|
317
317
|
|
318
318
|
@events.ssl_error self, addr, cert, e
|
319
319
|
rescue HttpParserError => e
|
320
|
-
client.
|
320
|
+
client.write_error(400)
|
321
321
|
client.close
|
322
322
|
|
323
323
|
@events.parse_error self, client.env, e
|
@@ -351,7 +351,10 @@ module Puma
|
|
351
351
|
@events.fire :state, :running
|
352
352
|
|
353
353
|
if background
|
354
|
-
@thread = Thread.new
|
354
|
+
@thread = Thread.new do
|
355
|
+
Puma.set_thread_name "server"
|
356
|
+
handle_servers
|
357
|
+
end
|
355
358
|
return @thread
|
356
359
|
else
|
357
360
|
handle_servers
|
@@ -463,6 +466,8 @@ module Puma
|
|
463
466
|
clean_thread_locals = @options[:clean_thread_locals]
|
464
467
|
close_socket = true
|
465
468
|
|
469
|
+
requests = 0
|
470
|
+
|
466
471
|
while true
|
467
472
|
case handle_request(client, buffer)
|
468
473
|
when false
|
@@ -476,7 +481,19 @@ module Puma
|
|
476
481
|
|
477
482
|
ThreadPool.clean_thread_locals if clean_thread_locals
|
478
483
|
|
479
|
-
|
484
|
+
requests += 1
|
485
|
+
|
486
|
+
check_for_more_data = @status == :run
|
487
|
+
|
488
|
+
if requests >= MAX_FAST_INLINE
|
489
|
+
# This will mean that reset will only try to use the data it already
|
490
|
+
# has buffered and won't try to read more data. What this means is that
|
491
|
+
# every client, independent of their request speed, gets treated like a slow
|
492
|
+
# one once every MAX_FAST_INLINE requests.
|
493
|
+
check_for_more_data = false
|
494
|
+
end
|
495
|
+
|
496
|
+
unless client.reset(check_for_more_data)
|
480
497
|
close_socket = false
|
481
498
|
client.set_timeout @persistent_timeout
|
482
499
|
@reactor.add client
|
@@ -505,7 +522,7 @@ module Puma
|
|
505
522
|
rescue HttpParserError => e
|
506
523
|
lowlevel_error(e, client.env)
|
507
524
|
|
508
|
-
client.
|
525
|
+
client.write_error(400)
|
509
526
|
|
510
527
|
@events.parse_error self, client.env, e
|
511
528
|
|
@@ -513,7 +530,7 @@ module Puma
|
|
513
530
|
rescue StandardError => e
|
514
531
|
lowlevel_error(e, client.env)
|
515
532
|
|
516
|
-
client.
|
533
|
+
client.write_error(500)
|
517
534
|
|
518
535
|
@events.unknown_error self, e, "Read"
|
519
536
|
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -87,8 +87,7 @@ module Puma
|
|
87
87
|
@spawned += 1
|
88
88
|
|
89
89
|
th = Thread.new(@spawned) do |spawned|
|
90
|
-
|
91
|
-
Thread.current.name = 'puma %03i' % spawned if Thread.current.respond_to?(:name=)
|
90
|
+
Puma.set_thread_name 'threadpool %03i' % spawned
|
92
91
|
todo = @todo
|
93
92
|
block = @block
|
94
93
|
mutex = @mutex
|
@@ -190,7 +189,7 @@ module Puma
|
|
190
189
|
# request, it might not be added to the `@todo` array right away.
|
191
190
|
# For example if a slow client has only sent a header, but not a body
|
192
191
|
# then the `@todo` array would stay the same size as the reactor works
|
193
|
-
# to try to buffer the request. In
|
192
|
+
# to try to buffer the request. In that scenario the next call to this
|
194
193
|
# method would not block and another request would be added into the reactor
|
195
194
|
# by the server. This would continue until a fully bufferend request
|
196
195
|
# makes it through the reactor and can then be processed by the thread pool.
|
@@ -244,10 +243,12 @@ module Puma
|
|
244
243
|
end
|
245
244
|
end
|
246
245
|
|
247
|
-
class
|
248
|
-
def initialize(pool, timeout)
|
246
|
+
class Automaton
|
247
|
+
def initialize(pool, timeout, thread_name, message)
|
249
248
|
@pool = pool
|
250
249
|
@timeout = timeout
|
250
|
+
@thread_name = thread_name
|
251
|
+
@message = message
|
251
252
|
@running = false
|
252
253
|
end
|
253
254
|
|
@@ -255,8 +256,9 @@ module Puma
|
|
255
256
|
@running = true
|
256
257
|
|
257
258
|
@thread = Thread.new do
|
259
|
+
Puma.set_thread_name @thread_name
|
258
260
|
while @running
|
259
|
-
@pool.
|
261
|
+
@pool.public_send(@message)
|
260
262
|
sleep @timeout
|
261
263
|
end
|
262
264
|
end
|
@@ -269,36 +271,12 @@ module Puma
|
|
269
271
|
end
|
270
272
|
|
271
273
|
def auto_trim!(timeout=30)
|
272
|
-
@auto_trim =
|
274
|
+
@auto_trim = Automaton.new(self, timeout, "threadpool trimmer", :trim)
|
273
275
|
@auto_trim.start!
|
274
276
|
end
|
275
277
|
|
276
|
-
class Reaper
|
277
|
-
def initialize(pool, timeout)
|
278
|
-
@pool = pool
|
279
|
-
@timeout = timeout
|
280
|
-
@running = false
|
281
|
-
end
|
282
|
-
|
283
|
-
def start!
|
284
|
-
@running = true
|
285
|
-
|
286
|
-
@thread = Thread.new do
|
287
|
-
while @running
|
288
|
-
@pool.reap
|
289
|
-
sleep @timeout
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
def stop
|
295
|
-
@running = false
|
296
|
-
@thread.wakeup
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
278
|
def auto_reap!(timeout=5)
|
301
|
-
@reaper =
|
279
|
+
@reaper = Automaton.new(self, timeout, "threadpool reaper", :reap)
|
302
280
|
@reaper.start!
|
303
281
|
end
|
304
282
|
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Use this Dockerfile to create minimal reproductions of issues
|
2
|
+
|
3
|
+
FROM ruby:2.6
|
4
|
+
|
5
|
+
# throw errors if Gemfile has been modified since Gemfile.lock
|
6
|
+
RUN bundle config --global frozen 1
|
7
|
+
|
8
|
+
WORKDIR /usr/src/app
|
9
|
+
|
10
|
+
COPY . .
|
11
|
+
RUN gem install bundler
|
12
|
+
RUN bundle install
|
13
|
+
RUN bundle exec rake compile
|
14
|
+
|
15
|
+
EXPOSE 9292
|
16
|
+
CMD bundle exec bin/puma test/rackup/hello.ru
|
data/tools/trickletest.rb
CHANGED
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: 4.
|
4
|
+
version: 4.3.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: 2019-
|
11
|
+
date: 2019-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nio4r
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- docs/restart.md
|
54
54
|
- docs/signals.md
|
55
55
|
- docs/systemd.md
|
56
|
+
- docs/tcp_mode.md
|
56
57
|
- ext/puma_http11/PumaHttp11Service.java
|
57
58
|
- ext/puma_http11/ext_help.h
|
58
59
|
- ext/puma_http11/extconf.rb
|
@@ -79,9 +80,6 @@ files:
|
|
79
80
|
- lib/puma/configuration.rb
|
80
81
|
- lib/puma/const.rb
|
81
82
|
- lib/puma/control_cli.rb
|
82
|
-
- lib/puma/convenient.rb
|
83
|
-
- lib/puma/daemon_ext.rb
|
84
|
-
- lib/puma/delegation.rb
|
85
83
|
- lib/puma/detect.rb
|
86
84
|
- lib/puma/dsl.rb
|
87
85
|
- lib/puma/events.rb
|
@@ -89,6 +87,7 @@ files:
|
|
89
87
|
- lib/puma/jruby_restart.rb
|
90
88
|
- lib/puma/launcher.rb
|
91
89
|
- lib/puma/minissl.rb
|
90
|
+
- lib/puma/minissl/context_builder.rb
|
92
91
|
- lib/puma/null_io.rb
|
93
92
|
- lib/puma/plugin.rb
|
94
93
|
- lib/puma/plugin/tmp_restart.rb
|
@@ -104,6 +103,7 @@ files:
|
|
104
103
|
- lib/puma/thread_pool.rb
|
105
104
|
- lib/puma/util.rb
|
106
105
|
- lib/rack/handler/puma.rb
|
106
|
+
- tools/docker/Dockerfile
|
107
107
|
- tools/jungle/README.md
|
108
108
|
- tools/jungle/init.d/README.md
|
109
109
|
- tools/jungle/init.d/puma
|
@@ -120,6 +120,7 @@ licenses:
|
|
120
120
|
- BSD-3-Clause
|
121
121
|
metadata:
|
122
122
|
msys2_mingw_dependencies: openssl
|
123
|
+
changelog_uri: https://github.com/puma/puma/blob/master/History.md
|
123
124
|
post_install_message:
|
124
125
|
rdoc_options: []
|
125
126
|
require_paths:
|