puma 3.6.2 → 3.7.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.

@@ -6,13 +6,9 @@ class String
6
6
  end
7
7
 
8
8
  unless method_defined? :byteslice
9
- if RUBY_VERSION < '1.9'
10
- alias_method :byteslice, :[]
11
- else
12
- def byteslice(*arg)
13
- enc = self.encoding
14
- self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
15
- end
9
+ def byteslice(*arg)
10
+ enc = self.encoding
11
+ self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
16
12
  end
17
13
  end
18
14
  end
@@ -1,5 +1,6 @@
1
1
  require 'puma/rack/builder'
2
2
  require 'puma/plugin'
3
+ require 'puma/const'
3
4
 
4
5
  module Puma
5
6
 
@@ -30,7 +31,7 @@ module Puma
30
31
  end
31
32
 
32
33
  def [](key)
33
- @set.each do |o|
34
+ @set.reverse_each do |o|
34
35
  if o.key? key
35
36
  return o[key]
36
37
  end
@@ -251,6 +252,7 @@ module Puma
251
252
  end
252
253
 
253
254
  if @options[:log_requests]
255
+ require 'puma/commonlogger'
254
256
  logger = @options[:logger]
255
257
  found = CommonLogger.new(found, logger)
256
258
  end
@@ -73,19 +73,14 @@ module Puma
73
73
  511 => 'Network Authentication Required'
74
74
  }
75
75
 
76
- SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
77
- [message.downcase.gsub(/\s|-|'/, '_').to_sym, code]
78
- }.flatten]
79
-
80
76
  # For some HTTP status codes the client only expects headers.
81
77
  #
82
78
 
83
- no_body = {}
84
- ((100..199).to_a << 204 << 205 << 304).each do |code|
85
- no_body[code] = true
86
- end
87
-
88
- STATUS_WITH_NO_ENTITY_BODY = no_body
79
+ STATUS_WITH_NO_ENTITY_BODY = {
80
+ 204 => true,
81
+ 205 => true,
82
+ 304 => true
83
+ }
89
84
 
90
85
  # Frequently used constants when constructing requests or responses. Many times
91
86
  # the constant just refers to a string with the same contents. Using these constants
@@ -100,8 +95,8 @@ module Puma
100
95
  # too taxing on performance.
101
96
  module Const
102
97
 
103
- PUMA_VERSION = VERSION = "3.6.2".freeze
104
- CODE_NAME = "Sleepy Sunday Serenity".freeze
98
+ PUMA_VERSION = VERSION = "3.7.0".freeze
99
+ CODE_NAME = "Snowy Sagebrush".freeze
105
100
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
106
101
 
107
102
  FAST_TRACK_KA_TIMEOUT = 0.2
@@ -118,15 +113,6 @@ module Puma
118
113
  # sending data back
119
114
  WRITE_TIMEOUT = 10
120
115
 
121
- # How long, after raising the ForceShutdown of a thread during
122
- # forced shutdown mode, to wait for the thread to try and finish
123
- # up it's work before leaving the thread to die on the vine.
124
- SHUTDOWN_GRACE_TIME = 5 # seconds
125
-
126
- DATE = "Date".freeze
127
-
128
- SCRIPT_NAME = "SCRIPT_NAME".freeze
129
-
130
116
  # The original URI requested by the client.
131
117
  REQUEST_URI= 'REQUEST_URI'.freeze
132
118
  REQUEST_PATH = 'REQUEST_PATH'.freeze
@@ -163,26 +149,12 @@ module Puma
163
149
  # Maximum request body size before it is moved out of memory and into a tempfile for reading.
164
150
  MAX_BODY = MAX_HEADER
165
151
 
166
- # A frozen format for this is about 15% faster
167
- STATUS_FORMAT = "HTTP/1.1 %d %s\r\nConnection: close\r\n".freeze
168
-
169
- CONTENT_TYPE = "Content-Type".freeze
170
-
171
- LAST_MODIFIED = "Last-Modified".freeze
172
- ETAG = "ETag".freeze
173
- SLASH = "/".freeze
174
152
  REQUEST_METHOD = "REQUEST_METHOD".freeze
175
- GET = "GET".freeze
176
153
  HEAD = "HEAD".freeze
177
154
  # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
178
- ETAG_FORMAT = "\"%x-%x-%x\"".freeze
179
155
  LINE_END = "\r\n".freeze
180
156
  REMOTE_ADDR = "REMOTE_ADDR".freeze
181
157
  HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
182
- HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
183
- HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
184
- REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n".freeze
185
- HOST = "HOST".freeze
186
158
 
187
159
  SERVER_NAME = "SERVER_NAME".freeze
188
160
  SERVER_PORT = "SERVER_PORT".freeze
@@ -195,7 +167,6 @@ module Puma
195
167
 
196
168
  SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
197
169
  HTTP_11 = "HTTP/1.1".freeze
198
- HTTP_10 = "HTTP/1.0".freeze
199
170
 
200
171
  SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
201
172
  GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
@@ -1,5 +1,5 @@
1
1
  require 'optparse'
2
- require 'puma'
2
+ require 'puma/state_file'
3
3
  require 'puma/const'
4
4
  require 'puma/detect'
5
5
  require 'puma/configuration'
@@ -179,39 +179,39 @@ module Puma
179
179
  end
180
180
 
181
181
  begin
182
- Process.getpgid @pid
183
- rescue SystemCallError
184
- if @command == "restart"
185
- start
186
- else
187
- raise "No pid '#{@pid}' found"
188
- end
189
- end
190
182
 
191
- case @command
192
- when "restart"
193
- Process.kill "SIGUSR2", @pid
183
+ case @command
184
+ when "restart"
185
+ Process.kill "SIGUSR2", @pid
194
186
 
195
- when "halt"
196
- Process.kill "QUIT", @pid
187
+ when "halt"
188
+ Process.kill "QUIT", @pid
197
189
 
198
- when "stop"
199
- Process.kill "SIGTERM", @pid
190
+ when "stop"
191
+ Process.kill "SIGTERM", @pid
200
192
 
201
- when "stats"
202
- puts "Stats not available via pid only"
203
- return
193
+ when "stats"
194
+ puts "Stats not available via pid only"
195
+ return
204
196
 
205
- when "reload-worker-directory"
206
- puts "reload-worker-directory not available via pid only"
207
- return
197
+ when "reload-worker-directory"
198
+ puts "reload-worker-directory not available via pid only"
199
+ return
208
200
 
209
- when "phased-restart"
210
- Process.kill "SIGUSR1", @pid
201
+ when "phased-restart"
202
+ Process.kill "SIGUSR1", @pid
211
203
 
212
- else
213
- message "Puma is started"
214
- return
204
+ else
205
+ message "Puma is started"
206
+ return
207
+ end
208
+
209
+ rescue SystemCallError
210
+ if @command == "restart"
211
+ start
212
+ else
213
+ raise "No pid '#{@pid}' found"
214
+ end
215
215
  end
216
216
 
217
217
  message "Command #{@command} sent success"
@@ -5,7 +5,9 @@ module Puma
5
5
  IS_JRUBY
6
6
  end
7
7
 
8
+ IS_WINDOWS = RUBY_PLATFORM =~ /mswin|ming|cygwin/
9
+
8
10
  def self.windows?
9
- RUBY_PLATFORM =~ /mswin|ming|cygwin/
11
+ IS_WINDOWS
10
12
  end
11
13
  end
@@ -1,4 +1,5 @@
1
1
  require 'puma/const'
2
+ require "puma/null_io"
2
3
  require 'stringio'
3
4
 
4
5
  module Puma
@@ -34,8 +35,6 @@ module Puma
34
35
 
35
36
  @debug = ENV.key? 'PUMA_DEBUG'
36
37
 
37
- @on_booted = []
38
-
39
38
  @hooks = Hash.new { |h,k| h[k] = [] }
40
39
  end
41
40
 
@@ -48,7 +47,7 @@ module Puma
48
47
  @hooks[hook].each { |t| t.call(*args) }
49
48
  end
50
49
 
51
- # Register a callbock for a given hook
50
+ # Register a callback for a given hook
52
51
  #
53
52
  def register(hook, obj=nil, &blk)
54
53
  if obj and blk
@@ -124,12 +123,12 @@ module Puma
124
123
  end
125
124
  end
126
125
 
127
- def on_booted(&b)
128
- @on_booted << b
126
+ def on_booted(&block)
127
+ register(:on_booted, &block)
129
128
  end
130
129
 
131
130
  def fire_on_booted!
132
- @on_booted.each { |b| b.call }
131
+ fire(:on_booted)
133
132
  end
134
133
 
135
134
  DEFAULT = new(STDOUT, STDERR)
@@ -1,6 +1,6 @@
1
1
  require 'puma/detect'
2
2
 
3
- if Puma::IS_JRUBY
3
+ if Puma.jruby?
4
4
  require 'puma/java_io_buffer'
5
5
  else
6
6
  require 'puma/puma_http11'
@@ -1,15 +1,12 @@
1
- require 'puma/server'
2
- require 'puma/const'
3
- require 'puma/configuration'
4
- require 'puma/binder'
1
+ require 'puma/events'
5
2
  require 'puma/detect'
6
- require 'puma/daemon_ext'
7
- require 'puma/util'
8
- require 'puma/single'
3
+
9
4
  require 'puma/cluster'
10
- require 'puma/state_file'
5
+ require 'puma/single'
11
6
 
12
- require 'puma/commonlogger'
7
+ require 'puma/const'
8
+
9
+ require 'puma/binder'
13
10
 
14
11
  module Puma
15
12
  # Puma::Launcher is the single entry point for starting a Puma server based on user
@@ -107,6 +104,8 @@ module Puma
107
104
  path = @options[:state]
108
105
  return unless path
109
106
 
107
+ require 'puma/state_file'
108
+
110
109
  sf = StateFile.new
111
110
  sf.pid = Process.pid
112
111
  sf.control_url = @options[:control_url]
@@ -256,6 +255,8 @@ module Puma
256
255
  ENV['PUMA_BUNDLER_PRUNED'] = '1'
257
256
  wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
258
257
  args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
258
+ # Ruby 2.0+ defaults to true which breaks socket activation
259
+ args += [{:close_others => false}] if RUBY_VERSION >= '2.0'
259
260
  Kernel.exec(*args)
260
261
  end
261
262
  end
@@ -1,42 +1,35 @@
1
1
  module Puma
2
-
3
2
  # Provides an IO-like object that always appears to contain no data.
4
3
  # Used as the value for rack.input when the request has no body.
5
4
  #
6
5
  class NullIO
7
- # Always returns nil
8
- #
9
6
  def gets
10
7
  nil
11
8
  end
12
9
 
13
- # Never yields
14
- #
15
10
  def each
16
11
  end
17
12
 
18
- # Mimics IO#read with no data
13
+ # Mimics IO#read with no data.
19
14
  #
20
- def read(count=nil,buffer=nil)
15
+ def read(count = nil, _buffer = nil)
21
16
  (count && count > 0) ? nil : ""
22
17
  end
23
18
 
24
- # Does nothing
25
- #
26
19
  def rewind
27
20
  end
28
21
 
29
- # Does nothing
30
- #
31
22
  def close
32
23
  end
33
24
 
34
- # Always zero
35
- #
36
25
  def size
37
26
  0
38
27
  end
39
28
 
29
+ def eof?
30
+ true
31
+ end
32
+
40
33
  def sync=(v)
41
34
  end
42
35
 
@@ -1,3 +1,6 @@
1
+ module Puma
2
+ end
3
+
1
4
  module Puma::Rack
2
5
  class Options
3
6
  def parse!(args)
@@ -43,15 +43,17 @@ module Puma::Rack
43
43
  def call(env)
44
44
  path = env['PATH_INFO']
45
45
  script_name = env['SCRIPT_NAME']
46
- hHost = env['HTTP_HOST']
47
- sName = env['SERVER_NAME']
48
- sPort = env['SERVER_PORT']
46
+ http_host = env['HTTP_HOST']
47
+ server_name = env['SERVER_NAME']
48
+ server_port = env['SERVER_PORT']
49
+
50
+ is_same_server = casecmp?(http_host, server_name) ||
51
+ casecmp?(http_host, "#{server_name}:#{server_port}")
49
52
 
50
53
  @mapping.each do |host, location, match, app|
51
- unless casecmp?(hHost, host) \
52
- || casecmp?(sName, host) \
53
- || (!host && (casecmp?(hHost, sName) ||
54
- casecmp?(hHost, sName+':'+sPort)))
54
+ unless casecmp?(http_host, host) \
55
+ || casecmp?(server_name, host) \
56
+ || (!host && is_same_server)
55
57
  next
56
58
  end
57
59
 
@@ -87,4 +89,3 @@ module Puma::Rack
87
89
  end
88
90
  end
89
91
  end
90
-
@@ -1,3 +1,6 @@
1
+ require 'puma/server'
2
+ require 'puma/const'
3
+
1
4
  module Puma
2
5
  class Runner
3
6
  def initialize(cli, events)
@@ -104,12 +107,20 @@ module Puma
104
107
  append = @options[:redirect_append]
105
108
 
106
109
  if stdout
110
+ unless Dir.exists?(File.dirname(stdout))
111
+ raise "Cannot redirect STDOUT to #{stdout}"
112
+ end
113
+
107
114
  STDOUT.reopen stdout, (append ? "a" : "w")
108
115
  STDOUT.sync = true
109
116
  STDOUT.puts "=== puma startup: #{Time.now} ==="
110
117
  end
111
118
 
112
119
  if stderr
120
+ unless Dir.exists?(File.dirname(stderr))
121
+ raise "Cannot redirect STDERR to #{stderr}"
122
+ end
123
+
113
124
  STDERR.reopen stderr, (append ? "a" : "w")
114
125
  STDERR.sync = true
115
126
  STDERR.puts "=== puma startup: #{Time.now} ==="
@@ -1,4 +1,6 @@
1
1
  require 'puma/runner'
2
+ require 'puma/detect'
3
+ require 'puma/plugin'
2
4
 
3
5
  module Puma
4
6
  class Single < Runner
@@ -4,10 +4,14 @@ module Puma
4
4
  # A simple thread pool management object.
5
5
  #
6
6
  class ThreadPool
7
-
8
7
  class ForceShutdown < RuntimeError
9
8
  end
10
9
 
10
+ # How long, after raising the ForceShutdown of a thread during
11
+ # forced shutdown mode, to wait for the thread to try and finish
12
+ # up its work before leaving the thread to die on the vine.
13
+ SHUTDOWN_GRACE_TIME = 5 # seconds
14
+
11
15
  # Maintain a minimum of +min+ and maximum of +max+ threads
12
16
  # in the pool.
13
17
  #
@@ -181,7 +185,9 @@ module Puma
181
185
  @spawned -= 1
182
186
  end
183
187
 
184
- @workers -= dead_workers
188
+ @workers.delete_if do |w|
189
+ dead_workers.include?(w)
190
+ end
185
191
  end
186
192
  end
187
193
 
@@ -257,18 +263,12 @@ module Puma
257
263
  @workers.dup
258
264
  end
259
265
 
260
- case timeout
261
- when -1
266
+ if timeout == -1
267
+ # Wait for threads to finish without force shutdown.
262
268
  threads.each(&:join)
263
- when 0
264
- threads.each do |t|
265
- t.raise ForceShutdown
266
- end
267
-
268
- threads.each do |t|
269
- t.join Const::SHUTDOWN_GRACE_TIME
270
- end
271
269
  else
270
+ # Wait for threads to finish after n attempts (+timeout+).
271
+ # If threads are still running, it will forcefully kill them.
272
272
  timeout.times do
273
273
  threads.delete_if do |t|
274
274
  t.join 1
@@ -286,7 +286,7 @@ module Puma
286
286
  end
287
287
 
288
288
  threads.each do |t|
289
- t.join Const::SHUTDOWN_GRACE_TIME
289
+ t.join SHUTDOWN_GRACE_TIME
290
290
  end
291
291
  end
292
292