puma 4.1.1 → 4.3.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.

@@ -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
@@ -62,8 +62,11 @@ module Puma
62
62
  end
63
63
 
64
64
  def fire_background
65
- @background.each do |b|
66
- Thread.new(&b)
65
+ @background.each_with_index do |b, i|
66
+ Thread.new do
67
+ Puma.set_thread_name "plugin background #{i}"
68
+ b.call
69
+ end
67
70
  end
68
71
  end
69
72
  end
@@ -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.write_500
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
- rescue IOError
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.write_400
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.write_500
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.write_408 if c.in_data_phase
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
@@ -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
- app.auth_token = token unless token.empty? || token == 'none'
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
@@ -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 Puma::Delegation
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
- forward :add_tcp_listener, :@binder
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 { handle_servers_lopez_mode }
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.write_400
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 { handle_servers }
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
@@ -505,7 +508,7 @@ module Puma
505
508
  rescue HttpParserError => e
506
509
  lowlevel_error(e, client.env)
507
510
 
508
- client.write_400
511
+ client.write_error(400)
509
512
 
510
513
  @events.parse_error self, client.env, e
511
514
 
@@ -513,7 +516,7 @@ module Puma
513
516
  rescue StandardError => e
514
517
  lowlevel_error(e, client.env)
515
518
 
516
- client.write_500
519
+ client.write_error(500)
517
520
 
518
521
  @events.unknown_error self, e, "Read"
519
522
 
@@ -87,8 +87,7 @@ module Puma
87
87
  @spawned += 1
88
88
 
89
89
  th = Thread.new(@spawned) do |spawned|
90
- # Thread name is new in Ruby 2.3
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 tha scenario the next call to this
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 AutoTrim
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.trim
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 = AutoTrim.new(self, timeout)
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 = Reaper.new(self, timeout)
279
+ @reaper = Automaton.new(self, timeout, "threadpool reaper", :reap)
302
280
  @reaper.start!
303
281
  end
304
282
 
@@ -61,8 +61,6 @@ module Rack
61
61
  conf
62
62
  end
63
63
 
64
-
65
-
66
64
  def self.run(app, options = {})
67
65
  conf = self.config(app, options)
68
66
 
@@ -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
@@ -38,7 +38,6 @@ ARGV[1].to_i.times do
38
38
  do_test(st, size)
39
39
  end
40
40
 
41
- t.abort_on_exception = true
42
41
  threads << t
43
42
  end
44
43
 
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.1.1
4
+ version: 4.3.0
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-09-09 00:00:00.000000000 Z
11
+ date: 2019-11-07 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:
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'puma/launcher'
4
- require 'puma/configuration'
5
-
6
- module Puma
7
- def self.run(opts={})
8
- cfg = Puma::Configuration.new do |user_config|
9
- if port = opts[:port]
10
- user_config.port port
11
- end
12
-
13
- user_config.quiet
14
-
15
- yield c
16
- end
17
-
18
- cfg.clamp
19
-
20
- events = Puma::Events.null
21
-
22
- launcher = Puma::Launcher.new cfg, :events => events
23
- launcher.run
24
- end
25
- end