puma 3.12.1 → 4.1.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.

data/lib/puma/events.rb CHANGED
@@ -29,8 +29,8 @@ module Puma
29
29
  #
30
30
  def initialize(stdout, stderr)
31
31
  @formatter = DefaultFormatter.new
32
- @stdout = stdout
33
- @stderr = stderr
32
+ @stdout = stdout.dup
33
+ @stderr = stderr.dup
34
34
 
35
35
  @stdout.sync = true
36
36
  @stderr.sync = true
@@ -93,7 +93,10 @@ module Puma
93
93
  # parsing exception.
94
94
  #
95
95
  def parse_error(server, env, error)
96
- @stderr.puts "#{Time.now}: HTTP parse error, malformed request (#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}): #{error.inspect}\n---\n"
96
+ @stderr.puts "#{Time.now}: HTTP parse error, malformed request " \
97
+ "(#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}#{env[REQUEST_PATH]}): " \
98
+ "#{error.inspect}" \
99
+ "\n---\n"
97
100
  end
98
101
 
99
102
  # An SSL error has occurred.
@@ -1,9 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'puma/detect'
4
-
5
- if Puma.jruby?
6
- require 'puma/java_io_buffer'
7
- else
8
- require 'puma/puma_http11'
9
- end
4
+ require 'puma/puma_http11'
data/lib/puma/launcher.rb CHANGED
@@ -63,6 +63,9 @@ module Puma
63
63
  @options = @config.options
64
64
  @config.clamp
65
65
 
66
+ @events.formatter = Events::PidFormatter.new if clustered?
67
+ @events.formatter = options[:log_formatter] if @options[:log_formatter]
68
+
66
69
  generate_restart_data
67
70
 
68
71
  if clustered? && !Process.respond_to?(:fork)
@@ -81,7 +84,6 @@ module Puma
81
84
  set_rack_environment
82
85
 
83
86
  if clustered?
84
- @events.formatter = Events::PidFormatter.new
85
87
  @options[:logger] = @events
86
88
 
87
89
  @runner = Cluster.new(self, @events)
@@ -214,6 +216,15 @@ module Puma
214
216
  end
215
217
  end
216
218
 
219
+ def close_binder_listeners
220
+ @binder.listeners.each do |l, io|
221
+ io.close
222
+ uri = URI.parse(l)
223
+ next unless uri.scheme == 'unix'
224
+ File.unlink("#{uri.host}#{uri.path}")
225
+ end
226
+ end
227
+
217
228
  private
218
229
 
219
230
  def reload_worker_directory
@@ -243,7 +254,7 @@ module Puma
243
254
 
244
255
  argv = restart_args
245
256
  Dir.chdir(@restart_dir)
246
- argv += [redirects] if RUBY_VERSION >= '1.9'
257
+ argv += [redirects]
247
258
  Kernel.exec(*argv)
248
259
  end
249
260
  end
@@ -272,7 +283,7 @@ module Puma
272
283
  wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
273
284
  args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
274
285
  # Ruby 2.0+ defaults to true which breaks socket activation
275
- args += [{:close_others => false}] if RUBY_VERSION >= '2.0'
286
+ args += [{:close_others => false}]
276
287
  Kernel.exec(*args)
277
288
  end
278
289
  end
@@ -319,16 +330,6 @@ module Puma
319
330
  @options[:prune_bundler] && clustered? && !@options[:preload_app]
320
331
  end
321
332
 
322
- def close_binder_listeners
323
- @binder.listeners.each do |l, io|
324
- io.close
325
- uri = URI.parse(l)
326
- next unless uri.scheme == 'unix'
327
- File.unlink("#{uri.host}#{uri.path}")
328
- end
329
- end
330
-
331
-
332
333
  def generate_restart_data
333
334
  if dir = @options[:directory]
334
335
  @restart_dir = dir
@@ -397,7 +398,7 @@ module Puma
397
398
  Signal.trap "SIGTERM" do
398
399
  graceful_stop
399
400
 
400
- raise SignalException, "SIGTERM"
401
+ raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
401
402
  end
402
403
  rescue Exception
403
404
  log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
data/lib/puma/minissl.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  begin
4
4
  require 'io/wait'
5
- rescue LoadError
5
+ rescue LoadError
6
6
  end
7
7
 
8
8
  module Puma
@@ -54,22 +54,21 @@ module Puma
54
54
  output = engine_read_all
55
55
  return output if output
56
56
 
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
57
+ data = @socket.read_nonblock(size, exception: false)
58
+ if data == :wait_readable || data == :wait_writable
59
+ # It would make more sense to let @socket.read_nonblock raise
60
+ # EAGAIN if necessary but it seems like it'll misbehave on Windows.
61
+ # I don't have a Windows machine to debug this so I can't explain
62
+ # exactly whats happening in that OS. Please let me know if you
63
+ # find out!
64
+ #
65
+ # In the meantime, we can emulate the correct behavior by
66
+ # capturing :wait_readable & :wait_writable and raising EAGAIN
67
+ # ourselves.
68
+ raise IO::EAGAINWaitReadable
69
+ elsif data.nil?
70
+ return nil
71
+ end
73
72
 
74
73
  @engine.inject(data)
75
74
  output = engine_read_all
@@ -177,6 +176,12 @@ module Puma
177
176
 
178
177
  class Context
179
178
  attr_accessor :verify_mode
179
+ attr_reader :no_tlsv1, :no_tlsv1_1
180
+
181
+ def initialize
182
+ @no_tlsv1 = false
183
+ @no_tlsv1_1 = false
184
+ end
180
185
 
181
186
  if defined?(JRUBY_VERSION)
182
187
  # jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
@@ -220,6 +225,19 @@ module Puma
220
225
  raise "Cert not configured" unless @cert
221
226
  end
222
227
  end
228
+
229
+ # disables TLSv1
230
+ def no_tlsv1=(tlsv1)
231
+ raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1)
232
+ @no_tlsv1 = tlsv1
233
+ end
234
+
235
+ # disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
236
+ def no_tlsv1_1=(tlsv1_1)
237
+ raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1_1)
238
+ @no_tlsv1_1 = tlsv1_1
239
+ end
240
+
223
241
  end
224
242
 
225
243
  VERIFY_NONE = 0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puma/plugin'
2
4
 
3
5
  Puma::Plugin.create do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Puma
2
4
  end
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Puma::Rack
2
4
  # Rack::URLMap takes a hash mapping urls or paths to apps, and
3
5
  # dispatches accordingly. Support for HTTP/1.1 host names exists if
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/handler/puma'
2
4
 
3
5
  module Rack::Handler
data/lib/puma/reactor.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'puma/util'
4
4
  require 'puma/minissl'
5
5
 
6
+ require 'nio'
7
+
6
8
  module Puma
7
9
  # Internal Docs, Not a public interface.
8
10
  #
@@ -18,12 +20,13 @@ module Puma
18
20
  #
19
21
  # ## Reactor Flow
20
22
  #
21
- # A request comes into a `Puma::Server` instance, it is then passed to a `Puma::Reactor` instance.
22
- # The reactor stores the request in an array and calls `IO.select` on the array in a loop.
23
+ # A connection comes into a `Puma::Server` instance, it is then passed to a `Puma::Reactor` instance,
24
+ # which stores it in an array and waits for any of the connections to be ready for reading.
23
25
  #
24
- # When the request is written to by the client then the `IO.select` will "wake up" and
26
+ # The waiting/wake up is performed with nio4r, which will use the appropriate backend (libev, Java NIO or
27
+ # just plain IO#select). The call to `NIO::Selector#select` will "wake up" and
25
28
  # return the references to any objects that caused it to "wake". The reactor
26
- # then loops through each of these request objects, and sees if they're complete. If they
29
+ # then loops through each of these request objects, and sees if they're complete. If they
27
30
  # have a full header and body then the reactor passes the request to a thread pool.
28
31
  # Once in a thread pool, a "worker thread" can run the the application's Ruby code against the request.
29
32
  #
@@ -38,7 +41,7 @@ module Puma
38
41
  # Creates an instance of Puma::Reactor
39
42
  #
40
43
  # The `server` argument is an instance of `Puma::Server`
41
- # this is used to write a response for "low level errors"
44
+ # that is used to write a response for "low level errors"
42
45
  # when there is an exception inside of the reactor.
43
46
  #
44
47
  # The `app_pool` is an instance of `Puma::ThreadPool`.
@@ -49,6 +52,8 @@ module Puma
49
52
  @events = server.events
50
53
  @app_pool = app_pool
51
54
 
55
+ @selector = NIO::Selector.new
56
+
52
57
  @mutex = Mutex.new
53
58
 
54
59
  # Read / Write pipes to wake up internal while loop
@@ -57,24 +62,26 @@ module Puma
57
62
  @sleep_for = DefaultSleepFor
58
63
  @timeouts = []
59
64
 
60
- @sockets = [@ready]
65
+ mon = @selector.register(@ready, :r)
66
+ mon.value = @ready
67
+
68
+ @monitors = [mon]
61
69
  end
62
70
 
63
71
  private
64
72
 
65
-
66
73
  # Until a request is added via the `add` method this method will internally
67
74
  # loop, waiting on the `sockets` array objects. The only object in this
68
75
  # array at first is the `@ready` IO object, which is the read end of a pipe
69
76
  # connected to `@trigger` object. When `@trigger` is written to, then the loop
70
- # will break on `IO.select` and return an array.
77
+ # will break on `NIO::Selector#select` and return an array.
71
78
  #
72
79
  # ## When a request is added:
73
80
  #
74
81
  # When the `add` method is called, an instance of `Puma::Client` is added to the `@input` array.
75
82
  # Next the `@ready` pipe is "woken" by writing a string of `"*"` to `@trigger`.
76
83
  #
77
- # When that happens, the internal loop stops blocking at `IO.select` and returns a reference
84
+ # When that happens, the internal loop stops blocking at `NIO::Selector#select` and returns a reference
78
85
  # to whatever "woke" it up. On the very first loop, the only thing in `sockets` is `@ready`.
79
86
  # When `@trigger` is written-to, the loop "wakes" and the `ready`
80
87
  # variable returns an array of arrays that looks like `[[#<IO:fd 10>], [], []]` where the
@@ -90,11 +97,11 @@ module Puma
90
97
  # to the `@ready` IO object. For example: `[#<IO:fd 10>, #<Puma::Client:0x3fdc1103bee8 @ready=false>]`.
91
98
  #
92
99
  # Since the `Puma::Client` in this example has data that has not been read yet,
93
- # the `IO.select` is immediately able to "wake" and read from the `Puma::Client`. At this point the
100
+ # the `NIO::Selector#select` is immediately able to "wake" and read from the `Puma::Client`. At this point the
94
101
  # `ready` output looks like this: `[[#<Puma::Client:0x3fdc1103bee8 @ready=false>], [], []]`.
95
102
  #
96
103
  # Each element in the first entry is iterated over. The `Puma::Client` object is not
97
- # the `@ready` pipe, so the reactor checks to see if it has the fully header and body with
104
+ # the `@ready` pipe, so the reactor checks to see if it has the full header and body with
98
105
  # the `Puma::Client#try_to_finish` method. If the full request has been sent,
99
106
  # then the request is passed off to the `@app_pool` thread pool so that a "worker thread"
100
107
  # can pick up the request and begin to execute application logic. This is done
@@ -102,56 +109,93 @@ module Puma
102
109
  #
103
110
  # If the request body is not present then nothing will happen, and the loop will iterate
104
111
  # again. When the client sends more data to the socket the `Puma::Client` object will
105
- # wake up the `IO.select` and it can again be checked to see if it's ready to be
112
+ # wake up the `NIO::Selector#select` and it can again be checked to see if it's ready to be
106
113
  # passed to the thread pool.
107
114
  #
108
115
  # ## Time Out Case
109
116
  #
110
- # In addition to being woken via a write to one of the sockets the `IO.select` will
117
+ # In addition to being woken via a write to one of the sockets the `NIO::Selector#select` will
111
118
  # periodically "time out" of the sleep. One of the functions of this is to check for
112
119
  # any requests that have "timed out". At the end of the loop it's checked to see if
113
- # the first element in the `@timeout` array has exceed it's allowed time. If so,
114
- # the client object is removed from the timeout aray, a 408 response is written.
115
- # Then it's connection is closed, and the object is removed from the `sockets` array
120
+ # the first element in the `@timeout` array has exceed its allowed time. If so,
121
+ # the client object is removed from the timeout array, a 408 response is written.
122
+ # Then its connection is closed, and the object is removed from the `sockets` array
116
123
  # that watches for new data.
117
124
  #
118
125
  # This behavior loops until all the objects that have timed out have been removed.
119
126
  #
120
- # Once all the timeouts have been processed, the next duration of the `IO.select` sleep
127
+ # Once all the timeouts have been processed, the next duration of the `NIO::Selector#select` sleep
121
128
  # will be set to be equal to the amount of time it will take for the next timeout to occur.
122
129
  # This calculation happens in `calculate_sleep`.
123
130
  def run_internal
124
- sockets = @sockets
131
+ monitors = @monitors
132
+ selector = @selector
125
133
 
126
134
  while true
127
135
  begin
128
- ready = IO.select sockets, nil, nil, @sleep_for
136
+ ready = selector.select @sleep_for
129
137
  rescue IOError => e
130
138
  Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
131
- if sockets.any? { |socket| socket.closed? }
139
+ if monitors.any? { |mon| mon.value.closed? }
132
140
  STDERR.puts "Error in select: #{e.message} (#{e.class})"
133
141
  STDERR.puts e.backtrace
134
- sockets = sockets.reject { |socket| socket.closed? }
142
+
143
+ monitors.reject! do |mon|
144
+ if mon.value.closed?
145
+ selector.deregister mon.value
146
+ true
147
+ end
148
+ end
149
+
135
150
  retry
136
151
  else
137
152
  raise
138
153
  end
139
154
  end
140
155
 
141
- if ready and reads = ready[0]
142
- reads.each do |c|
143
- if c == @ready
156
+ if ready
157
+ ready.each do |mon|
158
+ if mon.value == @ready
144
159
  @mutex.synchronize do
145
160
  case @ready.read(1)
146
161
  when "*"
147
- sockets += @input
162
+ @input.each do |c|
163
+ mon = nil
164
+ begin
165
+ begin
166
+ mon = selector.register(c, :r)
167
+ rescue ArgumentError
168
+ # There is a bug where we seem to be registering an already registered
169
+ # client. This code deals with this situation but I wish we didn't have to.
170
+ monitors.delete_if { |submon| submon.value.to_io == c.to_io }
171
+ selector.deregister(c)
172
+ mon = selector.register(c, :r)
173
+ end
174
+ rescue IOError
175
+ # Means that the io is closed, so we should ignore this request
176
+ # entirely
177
+ else
178
+ mon.value = c
179
+ @timeouts << mon if c.timeout_at
180
+ monitors << mon
181
+ end
182
+ end
148
183
  @input.clear
184
+
185
+ @timeouts.sort! { |a,b| a.value.timeout_at <=> b.value.timeout_at }
186
+ calculate_sleep
149
187
  when "c"
150
- sockets.delete_if do |s|
151
- if s == @ready
188
+ monitors.reject! do |submon|
189
+ if submon.value == @ready
152
190
  false
153
191
  else
154
- s.close
192
+ submon.value.close
193
+ begin
194
+ selector.deregister submon.value
195
+ rescue IOError
196
+ # nio4r on jruby seems to throw an IOError here if the IO is closed, so
197
+ # we need to swallow it.
198
+ end
155
199
  true
156
200
  end
157
201
  end
@@ -160,19 +204,21 @@ module Puma
160
204
  end
161
205
  end
162
206
  else
207
+ c = mon.value
208
+
163
209
  # We have to be sure to remove it from the timeout
164
210
  # list or we'll accidentally close the socket when
165
211
  # it's in use!
166
212
  if c.timeout_at
167
213
  @mutex.synchronize do
168
- @timeouts.delete c
214
+ @timeouts.delete mon
169
215
  end
170
216
  end
171
217
 
172
218
  begin
173
219
  if c.try_to_finish
174
220
  @app_pool << c
175
- sockets.delete c
221
+ clear_monitor mon
176
222
  end
177
223
 
178
224
  # Don't report these to the lowlevel_error handler, otherwise
@@ -182,18 +228,23 @@ module Puma
182
228
  c.write_500
183
229
  c.close
184
230
 
185
- sockets.delete c
231
+ clear_monitor mon
186
232
 
187
233
  # SSL handshake failure
188
234
  rescue MiniSSL::SSLError => e
189
235
  @server.lowlevel_error(e, c.env)
190
236
 
191
237
  ssl_socket = c.io
192
- addr = ssl_socket.peeraddr.last
238
+ begin
239
+ addr = ssl_socket.peeraddr.last
240
+ rescue IOError
241
+ addr = "<unknown>"
242
+ end
243
+
193
244
  cert = ssl_socket.peercert
194
245
 
195
246
  c.close
196
- sockets.delete c
247
+ clear_monitor mon
197
248
 
198
249
  @events.ssl_error @server, addr, cert, e
199
250
 
@@ -204,7 +255,7 @@ module Puma
204
255
  c.write_400
205
256
  c.close
206
257
 
207
- sockets.delete c
258
+ clear_monitor mon
208
259
 
209
260
  @events.parse_error @server, c.env, e
210
261
  rescue StandardError => e
@@ -213,7 +264,7 @@ module Puma
213
264
  c.write_500
214
265
  c.close
215
266
 
216
- sockets.delete c
267
+ clear_monitor mon
217
268
  end
218
269
  end
219
270
  end
@@ -223,11 +274,13 @@ module Puma
223
274
  @mutex.synchronize do
224
275
  now = Time.now
225
276
 
226
- while @timeouts.first.timeout_at < now
227
- c = @timeouts.shift
277
+ while @timeouts.first.value.timeout_at < now
278
+ mon = @timeouts.shift
279
+ c = mon.value
228
280
  c.write_408 if c.in_data_phase
229
281
  c.close
230
- sockets.delete c
282
+
283
+ clear_monitor mon
231
284
 
232
285
  break if @timeouts.empty?
233
286
  end
@@ -238,6 +291,11 @@ module Puma
238
291
  end
239
292
  end
240
293
 
294
+ def clear_monitor(mon)
295
+ @selector.deregister mon.value
296
+ @monitors.delete mon
297
+ end
298
+
241
299
  public
242
300
 
243
301
  def run
@@ -262,7 +320,7 @@ module Puma
262
320
  end
263
321
  end
264
322
 
265
- # The `calculate_sleep` sets the value that the `IO.select` will
323
+ # The `calculate_sleep` sets the value that the `NIO::Selector#select` will
266
324
  # sleep for in the main reactor loop when no sockets are being written to.
267
325
  #
268
326
  # The values kept in `@timeouts` are sorted so that the first timeout
@@ -276,7 +334,7 @@ module Puma
276
334
  if @timeouts.empty?
277
335
  @sleep_for = DefaultSleepFor
278
336
  else
279
- diff = @timeouts.first.timeout_at.to_f - Time.now.to_f
337
+ diff = @timeouts.first.value.timeout_at.to_f - Time.now.to_f
280
338
 
281
339
  if diff < 0.0
282
340
  @sleep_for = 0
@@ -293,18 +351,18 @@ module Puma
293
351
  # object.
294
352
  #
295
353
  # The main body of the reactor loop is in `run_internal` and it
296
- # will sleep on `IO.select`. When a new connection is added to the
297
- # reactor it cannot be added directly to the `sockets` aray, because
298
- # the `IO.select` will not be watching for it yet.
354
+ # will sleep on `NIO::Selector#select`. When a new connection is added to the
355
+ # reactor it cannot be added directly to the `sockets` array, because
356
+ # the `NIO::Selector#select` will not be watching for it yet.
299
357
  #
300
- # Instead what needs to happen is that `IO.select` needs to be woken up,
358
+ # Instead what needs to happen is that `NIO::Selector#select` needs to be woken up,
301
359
  # the contents of `@input` added to the `sockets` array, and then
302
- # another call to `IO.select` needs to happen. Since the `Puma::Client`
360
+ # another call to `NIO::Selector#select` needs to happen. Since the `Puma::Client`
303
361
  # object can be read immediately, it does not block, but instead returns
304
362
  # right away.
305
363
  #
306
364
  # This behavior is accomplished by writing to `@trigger` which wakes up
307
- # the `IO.select` and then there is logic to detect the value of `*`,
365
+ # the `NIO::Selector#select` and then there is logic to detect the value of `*`,
308
366
  # pull the contents from `@input` and add them to the sockets array.
309
367
  #
310
368
  # If the object passed in has a timeout value in `timeout_at` then
@@ -315,13 +373,6 @@ module Puma
315
373
  @mutex.synchronize do
316
374
  @input << c
317
375
  @trigger << "*"
318
-
319
- if c.timeout_at
320
- @timeouts << c
321
- @timeouts.sort! { |a,b| a.timeout_at <=> b.timeout_at }
322
-
323
- calculate_sleep
324
- end
325
376
  end
326
377
  end
327
378