puma 3.12.0 → 4.0.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.

Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +36 -0
  3. data/README.md +29 -9
  4. data/docs/architecture.md +1 -0
  5. data/docs/deployment.md +24 -4
  6. data/docs/restart.md +4 -2
  7. data/docs/systemd.md +27 -9
  8. data/ext/puma_http11/PumaHttp11Service.java +2 -0
  9. data/ext/puma_http11/mini_ssl.c +32 -4
  10. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
  11. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +11 -4
  12. data/lib/puma/app/status.rb +3 -2
  13. data/lib/puma/binder.rb +19 -10
  14. data/lib/puma/cli.rb +2 -0
  15. data/lib/puma/client.rb +46 -25
  16. data/lib/puma/cluster.rb +40 -14
  17. data/lib/puma/commonlogger.rb +2 -0
  18. data/lib/puma/configuration.rb +4 -1
  19. data/lib/puma/const.rb +8 -2
  20. data/lib/puma/control_cli.rb +21 -9
  21. data/lib/puma/convenient.rb +2 -0
  22. data/lib/puma/daemon_ext.rb +2 -0
  23. data/lib/puma/delegation.rb +2 -0
  24. data/lib/puma/detect.rb +2 -0
  25. data/lib/puma/dsl.rb +57 -5
  26. data/lib/puma/events.rb +2 -0
  27. data/lib/puma/io_buffer.rb +3 -6
  28. data/lib/puma/jruby_restart.rb +2 -0
  29. data/lib/puma/launcher.rb +14 -13
  30. data/lib/puma/minissl.rb +15 -1
  31. data/lib/puma/null_io.rb +2 -0
  32. data/lib/puma/plugin.rb +2 -0
  33. data/lib/puma/rack/builder.rb +2 -1
  34. data/lib/puma/reactor.rb +106 -53
  35. data/lib/puma/runner.rb +3 -1
  36. data/lib/puma/server.rb +27 -24
  37. data/lib/puma/single.rb +4 -2
  38. data/lib/puma/state_file.rb +2 -0
  39. data/lib/puma/tcp_logger.rb +2 -0
  40. data/lib/puma/thread_pool.rb +7 -1
  41. data/lib/puma/util.rb +2 -6
  42. data/lib/rack/handler/puma.rb +3 -0
  43. data/tools/jungle/init.d/puma +5 -5
  44. metadata +19 -8
  45. data/lib/puma/compat.rb +0 -14
  46. data/lib/puma/java_io_buffer.rb +0 -45
  47. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
data/lib/puma/runner.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puma/server'
2
4
  require 'puma/const'
3
5
 
@@ -53,7 +55,7 @@ module Puma
53
55
  app = Puma::App::Status.new @launcher
54
56
 
55
57
  if token = @options[:control_auth_token]
56
- app.auth_token = token unless token.empty? or token == :none
58
+ app.auth_token = token unless token.empty? || token == 'none'
57
59
  end
58
60
 
59
61
  control = Puma::Server.new app, @launcher.events
data/lib/puma/server.rb CHANGED
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringio'
2
4
 
3
5
  require 'puma/thread_pool'
4
6
  require 'puma/const'
5
7
  require 'puma/events'
6
8
  require 'puma/null_io'
7
- require 'puma/compat'
8
9
  require 'puma/reactor'
9
10
  require 'puma/client'
10
11
  require 'puma/binder'
@@ -14,10 +15,6 @@ require 'puma/util'
14
15
 
15
16
  require 'puma/puma_http11'
16
17
 
17
- unless Puma.const_defined? "IOBuffer"
18
- require 'puma/io_buffer'
19
- end
20
-
21
18
  require 'socket'
22
19
 
23
20
  module Puma
@@ -26,7 +23,7 @@ module Puma
26
23
  #
27
24
  # This class is used by the `Puma::Single` and `Puma::Cluster` classes
28
25
  # to generate one or more `Puma::Server` instances capable of handling requests.
29
- # Each Puma process will contain one `Puma::Server` instacne.
26
+ # Each Puma process will contain one `Puma::Server` instance.
30
27
  #
31
28
  # The `Puma::Server` instance pulls requests from the socket, adds them to a
32
29
  # `Puma::Reactor` where they get eventually passed to a `Puma::ThreadPool`.
@@ -77,7 +74,6 @@ module Puma
77
74
  @first_data_timeout = options.fetch(:first_data_timeout, FIRST_DATA_TIMEOUT)
78
75
 
79
76
  @binder = Binder.new(events)
80
- @own_binder = true
81
77
 
82
78
  @leak_stack_on_error = true
83
79
 
@@ -100,7 +96,6 @@ module Puma
100
96
 
101
97
  def inherit_binder(bind)
102
98
  @binder = bind
103
- @own_binder = false
104
99
  end
105
100
 
106
101
  def tcp_mode!
@@ -268,10 +263,11 @@ module Puma
268
263
  Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
269
264
  end
270
265
 
271
- @notify.close
272
-
273
- if @status != :restart and @own_binder
274
- @binder.close
266
+ # Prevent can't modify frozen IOError (RuntimeError)
267
+ begin
268
+ @notify.close
269
+ rescue IOError
270
+ # no biggy
275
271
  end
276
272
  end
277
273
 
@@ -396,7 +392,10 @@ module Puma
396
392
  end
397
393
 
398
394
  pool << client
399
- pool.wait_until_not_full
395
+ busy_threads = pool.wait_until_not_full
396
+ if busy_threads == 0
397
+ @options[:out_of_band].each(&:call) if @options[:out_of_band]
398
+ end
400
399
  end
401
400
  rescue SystemCallError
402
401
  # nothing
@@ -428,10 +427,6 @@ module Puma
428
427
  ensure
429
428
  @check.close
430
429
  @notify.close
431
-
432
- if @status != :restart and @own_binder
433
- @binder.close
434
- end
435
430
  end
436
431
 
437
432
  @events.fire :state, :done
@@ -597,15 +592,19 @@ module Puma
597
592
  env['HTTP_X_FORWARDED_PROTO'] == 'https' ? PORT_443 : PORT_80
598
593
  end
599
594
 
600
- # Given the request +env+ from +client+ and a partial request body
601
- # in +body+, finish reading the body if there is one and invoke
602
- # the rack app. Then construct the response and write it back to
603
- # +client+
595
+ # Takes the request +req+, invokes the Rack application to construct
596
+ # the response and writes it back to +req.io+.
597
+ #
598
+ # The second parameter +lines+ is a IO-like object unique to this thread.
599
+ # This is normally an instance of Puma::IOBuffer.
604
600
  #
605
- # +cl+ is the previously fetched Content-Length header if there
606
- # was one. This is an optimization to keep from having to look
607
- # it up again.
601
+ # It'll return +false+ when the connection is closed, this doesn't mean
602
+ # that the response wasn't successful.
608
603
  #
604
+ # It'll return +:async+ if the connection remains open but will be handled
605
+ # elsewhere, i.e. the connection has been hijacked by the Rack application.
606
+ #
607
+ # Finally, it'll return +true+ on keep-alive connections.
609
608
  def handle_request(req, lines)
610
609
  env = req.env
611
610
  client = req.io
@@ -940,6 +939,10 @@ module Puma
940
939
  @events.debug "Drained #{count} additional connections."
941
940
  end
942
941
 
942
+ if @status != :restart
943
+ @binder.close
944
+ end
945
+
943
946
  if @thread_pool
944
947
  if timeout = @options[:force_shutdown_after]
945
948
  @thread_pool.shutdown timeout.to_i
data/lib/puma/single.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puma/runner'
2
4
  require 'puma/detect'
3
5
  require 'puma/plugin'
@@ -24,7 +26,7 @@ module Puma
24
26
  end
25
27
 
26
28
  def stop
27
- @server.stop false
29
+ @server.stop(false) if @server
28
30
  end
29
31
 
30
32
  def halt
@@ -34,7 +36,7 @@ module Puma
34
36
  def stop_blocked
35
37
  log "- Gracefully stopping, waiting for requests to finish"
36
38
  @control.stop(true) if @control
37
- @server.stop(true)
39
+ @server.stop(true) if @server
38
40
  end
39
41
 
40
42
  def jruby_daemon?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  module Puma
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Puma
2
4
  class TCPLogger
3
5
  def initialize(logger, app, quiet=false)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
 
3
5
  module Puma
@@ -192,6 +194,9 @@ module Puma
192
194
  # method would not block and another request would be added into the reactor
193
195
  # by the server. This would continue until a fully bufferend request
194
196
  # makes it through the reactor and can then be processed by the thread pool.
197
+ #
198
+ # Returns the current number of busy threads, or +nil+ if shutting down.
199
+ #
195
200
  def wait_until_not_full
196
201
  @mutex.synchronize do
197
202
  while true
@@ -201,7 +206,8 @@ module Puma
201
206
  # is work queued that cannot be handled by waiting
202
207
  # threads, then accept more work until we would
203
208
  # spin up the max number of threads.
204
- return if @todo.size - @waiting < @max - @spawned
209
+ busy_threads = @spawned - @waiting + @todo.size
210
+ return busy_threads if @max > busy_threads
205
211
 
206
212
  @not_full.wait @mutex
207
213
  end
data/lib/puma/util.rb CHANGED
@@ -1,10 +1,6 @@
1
- major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
1
+ # frozen_string_literal: true
2
2
 
3
- if major == 1 && minor == 9 && patch == 3 && RUBY_PATCHLEVEL < 125
4
- require 'puma/rack/backports/uri/common_193'
5
- else
6
- require 'uri/common'
7
- end
3
+ require 'uri/common'
8
4
 
9
5
  module Puma
10
6
  module Util
@@ -49,6 +49,9 @@ module Rack
49
49
  self.set_host_port_to_config(host, port, user_config)
50
50
  end
51
51
 
52
+ if default_options[:Host]
53
+ file_config.set_default_host(default_options[:Host])
54
+ end
52
55
  self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
53
56
 
54
57
  user_config.app app
@@ -47,11 +47,11 @@ do_start_one() {
47
47
  PIDFILE=$1/tmp/puma/pid
48
48
  if [ -e $PIDFILE ]; then
49
49
  PID=`cat $PIDFILE`
50
- # If the puma isn't running, run it, otherwise restart it.
50
+ # If the puma is running, restart it, otherwise run it.
51
51
  if ps -p $PID > /dev/null; then
52
- do_start_one_do $1
53
- else
54
52
  do_restart_one $1
53
+ else
54
+ do_start_one_do $1
55
55
  fi
56
56
  else
57
57
  do_start_one_do $1
@@ -106,8 +106,6 @@ do_stop_one() {
106
106
  if [ -e $PIDFILE ]; then
107
107
  PID=`cat $PIDFILE`
108
108
  if ps -p $PID > /dev/null; then
109
- log_daemon_msg "---> Puma $1 isn't running."
110
- else
111
109
  log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
112
110
  if [ "$USE_LOCAL_BUNDLE" -eq 1 ]; then
113
111
  cd $1 && bundle exec pumactl --state $STATEFILE stop
@@ -116,6 +114,8 @@ do_stop_one() {
116
114
  fi
117
115
  # Many daemons don't delete their pidfiles when they exit.
118
116
  rm -f $PIDFILE $STATEFILE
117
+ else
118
+ log_daemon_msg "---> Puma $1 isn't running."
119
119
  fi
120
120
  else
121
121
  log_daemon_msg "---> No puma here..."
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.12.0
4
+ version: 4.0.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: 2018-07-13 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2019-06-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nio4r
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
13
27
  description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
14
28
  for Ruby/Rack applications. Puma is intended for use in both development and production
15
29
  environments. It's great for highly concurrent Ruby implementations such as Rubinius
@@ -51,6 +65,7 @@ files:
51
65
  - ext/puma_http11/mini_ssl.c
52
66
  - ext/puma_http11/org/jruby/puma/Http11.java
53
67
  - ext/puma_http11/org/jruby/puma/Http11Parser.java
68
+ - ext/puma_http11/org/jruby/puma/IOBuffer.java
54
69
  - ext/puma_http11/org/jruby/puma/MiniSSL.java
55
70
  - ext/puma_http11/puma_http11.c
56
71
  - lib/puma.rb
@@ -61,7 +76,6 @@ files:
61
76
  - lib/puma/client.rb
62
77
  - lib/puma/cluster.rb
63
78
  - lib/puma/commonlogger.rb
64
- - lib/puma/compat.rb
65
79
  - lib/puma/configuration.rb
66
80
  - lib/puma/const.rb
67
81
  - lib/puma/control_cli.rb
@@ -72,14 +86,12 @@ files:
72
86
  - lib/puma/dsl.rb
73
87
  - lib/puma/events.rb
74
88
  - lib/puma/io_buffer.rb
75
- - lib/puma/java_io_buffer.rb
76
89
  - lib/puma/jruby_restart.rb
77
90
  - lib/puma/launcher.rb
78
91
  - lib/puma/minissl.rb
79
92
  - lib/puma/null_io.rb
80
93
  - lib/puma/plugin.rb
81
94
  - lib/puma/plugin/tmp_restart.rb
82
- - lib/puma/rack/backports/uri/common_193.rb
83
95
  - lib/puma/rack/builder.rb
84
96
  - lib/puma/rack/urlmap.rb
85
97
  - lib/puma/rack_default.rb
@@ -123,8 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
135
  - !ruby/object:Gem::Version
124
136
  version: '0'
125
137
  requirements: []
126
- rubyforge_project:
127
- rubygems_version: 2.7.6
138
+ rubygems_version: 3.0.3
128
139
  signing_key:
129
140
  specification_version: 4
130
141
  summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
data/lib/puma/compat.rb DELETED
@@ -1,14 +0,0 @@
1
- # Provides code to work properly on 1.8 and 1.9
2
-
3
- class String
4
- unless method_defined? :bytesize
5
- alias_method :bytesize, :size
6
- end
7
-
8
- unless method_defined? :byteslice
9
- def byteslice(*arg)
10
- enc = self.encoding
11
- self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
12
- end
13
- end
14
- end
@@ -1,45 +0,0 @@
1
- require 'java'
2
-
3
- # Conservative native JRuby/Java implementation of IOBuffer
4
- # backed by a ByteArrayOutputStream and conversion between
5
- # Ruby String and Java bytes
6
- module Puma
7
- class JavaIOBuffer < java.io.ByteArrayOutputStream
8
- field_reader :buf
9
- end
10
-
11
- class IOBuffer
12
- BUF_DEFAULT_SIZE = 4096
13
-
14
- def initialize
15
- @buf = JavaIOBuffer.new(BUF_DEFAULT_SIZE)
16
- end
17
-
18
- def reset
19
- @buf.reset
20
- end
21
-
22
- def <<(str)
23
- bytes = str.to_java_bytes
24
- @buf.write(bytes, 0, bytes.length)
25
- end
26
-
27
- def append(*strs)
28
- strs.each { |s| self << s; }
29
- end
30
-
31
- def to_s
32
- String.from_java_bytes @buf.to_byte_array
33
- end
34
-
35
- alias_method :to_str, :to_s
36
-
37
- def used
38
- @buf.size
39
- end
40
-
41
- def capacity
42
- @buf.buf.length
43
- end
44
- end
45
- end
@@ -1,33 +0,0 @@
1
- # :stopdoc:
2
-
3
- require 'uri/common'
4
-
5
- # Issue:
6
- # http://bugs.ruby-lang.org/issues/5925
7
- #
8
- # Relevant commit:
9
- # https://github.com/ruby/ruby/commit/edb7cdf1eabaff78dfa5ffedfbc2e91b29fa9ca1
10
-
11
-
12
- module URI
13
- begin
14
- 256.times do |i|
15
- TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
16
- end
17
- TBLENCWWWCOMP_[' '] = '+'
18
- TBLENCWWWCOMP_.freeze
19
-
20
- 256.times do |i|
21
- h, l = i>>4, i&15
22
- TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
23
- TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
24
- TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
25
- TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
26
- end
27
- TBLDECWWWCOMP_['+'] = ' '
28
- TBLDECWWWCOMP_.freeze
29
- rescue Exception
30
- end
31
- end
32
-
33
- # :startdoc: