puma 2.10.2 → 2.11.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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/History.txt +33 -0
- data/ext/puma_http11/extconf.rb +3 -3
- data/lib/puma/app/status.rb +7 -0
- data/lib/puma/binder.rb +28 -4
- data/lib/puma/cli.rb +7 -3
- data/lib/puma/client.rb +8 -0
- data/lib/puma/cluster.rb +15 -3
- data/lib/puma/configuration.rb +25 -0
- data/lib/puma/const.rb +2 -2
- data/lib/puma/control_cli.rb +5 -1
- data/lib/puma/events.rb +20 -17
- data/lib/puma/server.rb +27 -12
- data/lib/puma/single.rb +3 -3
- data/lib/puma/thread_pool.rb +18 -6
- data/lib/rack/handler/puma.rb +0 -5
- data/test/test_integration.rb +41 -0
- data/tools/jungle/init.d/puma +19 -4
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e1ad09e6adf2941686edf7a317cfabf117d6dc9
|
4
|
+
data.tar.gz: aace15466553dbf47588663c2d72fce3e2a300c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ac4aebd582d8f25e19b74840b7c47f8959ded867413966e56df5b97dc54e2b3e6dc2762ddae777e4826038d5ebb35d61a0a9811dd847ac6617b3586b5d47c00
|
7
|
+
data.tar.gz: dcb9ef0b1a9cff3e869e65dab007953177e6e3fc4e4ada116228f05cb446655f83cca4945c4b512c9c608aba9bedf78de3a3168a970200cf248227183e32ac8e
|
data/Gemfile
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
=== 2.11.0 / 2015-01-20
|
2
|
+
|
3
|
+
* 9 bug fixes:
|
4
|
+
* Add mode as an additional bind option to unix sockets. Fixes #630
|
5
|
+
* Advertise HTTPS properly after a hot restart
|
6
|
+
* Don't write lowlevel_error_handler to state
|
7
|
+
* Fix phased restart with stuck requests
|
8
|
+
* Handle spaces in the path properly. Fixes #622
|
9
|
+
* Set a default REMOTE_ADDR to avoid using peeraddr on unix sockets. Fixes #583
|
10
|
+
* Skip device number checking on jruby. Fixes #586
|
11
|
+
* Update extconf.rb to compile correctly on OS X
|
12
|
+
* redirect io right after daemonizing so startup errors are shown. Fixes #359
|
13
|
+
|
14
|
+
* 6 minor features:
|
15
|
+
* Add a configuration option that prevents puma from queueing requests.
|
16
|
+
* Add reload_worker_directory
|
17
|
+
* Add the ability to pass environment variables to the init script (for Jungle).
|
18
|
+
* Add the proctitle tag to the worker. Fixes #633
|
19
|
+
* Infer a proctitle tag based on the directory
|
20
|
+
* Update lowlevel error message to be more meaningful.
|
21
|
+
|
22
|
+
* 10 PRs merged:
|
23
|
+
* Merge pull request #478 from rubencaro/master
|
24
|
+
* Merge pull request #610 from kwilczynski/master
|
25
|
+
* Merge pull request #611 from jasonl/better-lowlevel-message
|
26
|
+
* Merge pull request #616 from jc00ke/master
|
27
|
+
* Merge pull request #623 from raldred/patch-1
|
28
|
+
* Merge pull request #628 from rdpoor/master
|
29
|
+
* Merge pull request #634 from deepj/master
|
30
|
+
* Merge pull request #637 from raskhadafi/patch-1
|
31
|
+
* Merge pull request #639 from ebeigarts/fix-phased-restarts
|
32
|
+
* Merge pull request #640 from codehotter/issue-612-dependent-requests-deadlock
|
33
|
+
|
1
34
|
=== 2.10.2 / 2014-11-26
|
2
35
|
|
3
36
|
* 1 bug fix:
|
data/ext/puma_http11/extconf.rb
CHANGED
@@ -2,8 +2,8 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
dir_config("puma_http11")
|
4
4
|
|
5
|
-
if %w'
|
6
|
-
|
7
|
-
|
5
|
+
if %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} and
|
6
|
+
%w'ssl ssleay32'.find {|ssl| have_library(ssl, 'SSL_CTX_new')}
|
7
|
+
|
8
8
|
create_makefile("puma/puma_http11")
|
9
9
|
end
|
data/lib/puma/app/status.rb
CHANGED
@@ -48,6 +48,13 @@ module Puma
|
|
48
48
|
return rack_response(200, OK_STATUS)
|
49
49
|
end
|
50
50
|
|
51
|
+
when /\/reload-worker-directory$/
|
52
|
+
if !@cli.reload_worker_directory
|
53
|
+
return rack_response(404, '{ "error": "reload_worker_directory not available" }')
|
54
|
+
else
|
55
|
+
return rack_response(200, OK_STATUS)
|
56
|
+
end
|
57
|
+
|
51
58
|
when /\/stats$/
|
52
59
|
return rack_response(200, @cli.stats)
|
53
60
|
else
|
data/lib/puma/binder.rb
CHANGED
@@ -98,7 +98,7 @@ module Puma
|
|
98
98
|
|
99
99
|
@listeners << [str, io]
|
100
100
|
when "unix"
|
101
|
-
path = "#{uri.host}#{uri.path}"
|
101
|
+
path = "#{uri.host}#{uri.path}".gsub("%20", " ")
|
102
102
|
|
103
103
|
if fd = @inherited_fds.delete(str)
|
104
104
|
logger.log "* Inherited #{str}"
|
@@ -107,6 +107,7 @@ module Puma
|
|
107
107
|
logger.log "* Listening on #{str}"
|
108
108
|
|
109
109
|
umask = nil
|
110
|
+
mode = nil
|
110
111
|
|
111
112
|
if uri.query
|
112
113
|
params = Rack::Utils.parse_query uri.query
|
@@ -114,9 +115,13 @@ module Puma
|
|
114
115
|
# Use Integer() to respect the 0 prefix as octal
|
115
116
|
umask = Integer(u)
|
116
117
|
end
|
118
|
+
|
119
|
+
if u = params['mode']
|
120
|
+
mode = Integer('0'+u)
|
121
|
+
end
|
117
122
|
end
|
118
123
|
|
119
|
-
io = add_unix_listener path, umask
|
124
|
+
io = add_unix_listener path, umask, mode
|
120
125
|
end
|
121
126
|
|
122
127
|
@listeners << [str, io]
|
@@ -247,13 +252,20 @@ module Puma
|
|
247
252
|
def inherited_ssl_listener(fd, ctx)
|
248
253
|
require 'puma/minissl'
|
249
254
|
s = TCPServer.for_fd(fd)
|
250
|
-
|
255
|
+
ssl = MiniSSL::Server.new(s, ctx)
|
256
|
+
|
257
|
+
env = @proto_env.dup
|
258
|
+
env[HTTPS_KEY] = HTTPS
|
259
|
+
@envs[ssl] = env
|
260
|
+
|
261
|
+
@ios << ssl
|
262
|
+
|
251
263
|
s
|
252
264
|
end
|
253
265
|
|
254
266
|
# Tell the server to listen on +path+ as a UNIX domain socket.
|
255
267
|
#
|
256
|
-
def add_unix_listener(path, umask=nil)
|
268
|
+
def add_unix_listener(path, umask=nil, mode=nil)
|
257
269
|
@unix_paths << path
|
258
270
|
|
259
271
|
# Let anyone connect by default
|
@@ -279,6 +291,14 @@ module Puma
|
|
279
291
|
File.umask old_mask
|
280
292
|
end
|
281
293
|
|
294
|
+
if mode
|
295
|
+
File.chmod mode, path
|
296
|
+
end
|
297
|
+
|
298
|
+
env = @proto_env.dup
|
299
|
+
env[REMOTE_ADDR] = "127.0.0.1"
|
300
|
+
@envs[s] = env
|
301
|
+
|
282
302
|
s
|
283
303
|
end
|
284
304
|
|
@@ -292,6 +312,10 @@ module Puma
|
|
292
312
|
end
|
293
313
|
@ios << s
|
294
314
|
|
315
|
+
env = @proto_env.dup
|
316
|
+
env[REMOTE_ADDR] = "127.0.0.1"
|
317
|
+
@envs[s] = env
|
318
|
+
|
295
319
|
s
|
296
320
|
end
|
297
321
|
|
data/lib/puma/cli.rb
CHANGED
@@ -229,7 +229,7 @@ module Puma
|
|
229
229
|
|
230
230
|
cfg = @config.dup
|
231
231
|
|
232
|
-
[ :logger, :before_worker_shutdown, :before_worker_boot, :after_worker_boot, :on_restart ].each { |o| cfg.options.delete o }
|
232
|
+
[ :logger, :before_worker_shutdown, :before_worker_boot, :after_worker_boot, :on_restart, :lowlevel_error_handler ].each { |o| cfg.options.delete o }
|
233
233
|
|
234
234
|
state["config"] = cfg
|
235
235
|
|
@@ -335,7 +335,7 @@ module Puma
|
|
335
335
|
s_env = File.stat(dir)
|
336
336
|
s_pwd = File.stat(Dir.pwd)
|
337
337
|
|
338
|
-
if s_env.ino == s_pwd.ino and s_env.dev == s_pwd.dev
|
338
|
+
if s_env.ino == s_pwd.ino and (jruby? or s_env.dev == s_pwd.dev)
|
339
339
|
@restart_dir = dir
|
340
340
|
@options[:worker_directory] = dir
|
341
341
|
end
|
@@ -491,7 +491,7 @@ module Puma
|
|
491
491
|
set_rack_environment
|
492
492
|
|
493
493
|
if clustered?
|
494
|
-
@events =
|
494
|
+
@events.formatter = Events::PidFormatter.new
|
495
495
|
@options[:logger] = @events
|
496
496
|
|
497
497
|
@runner = Cluster.new(self)
|
@@ -572,6 +572,10 @@ module Puma
|
|
572
572
|
@runner.restart
|
573
573
|
end
|
574
574
|
|
575
|
+
def reload_worker_directory
|
576
|
+
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
577
|
+
end
|
578
|
+
|
575
579
|
def phased_restart
|
576
580
|
unless @runner.respond_to?(:phased_restart) and @runner.phased_restart
|
577
581
|
log "* phased-restart called but not available, restarting normally."
|
data/lib/puma/client.rb
CHANGED
@@ -222,6 +222,14 @@ module Puma
|
|
222
222
|
end
|
223
223
|
end # IS_JRUBY
|
224
224
|
|
225
|
+
def finish
|
226
|
+
return true if @ready
|
227
|
+
until try_to_finish
|
228
|
+
IO.select([@to_io], nil, nil)
|
229
|
+
end
|
230
|
+
true
|
231
|
+
end
|
232
|
+
|
225
233
|
def read_body
|
226
234
|
# Read an odd sized chunk so we can read even sized ones
|
227
235
|
# after this
|
data/lib/puma/cluster.rb
CHANGED
@@ -43,12 +43,14 @@ module Puma
|
|
43
43
|
end
|
44
44
|
|
45
45
|
class Worker
|
46
|
-
def initialize(idx, pid, phase)
|
46
|
+
def initialize(idx, pid, phase, options)
|
47
47
|
@index = idx
|
48
48
|
@pid = pid
|
49
49
|
@phase = phase
|
50
50
|
@stage = :started
|
51
51
|
@signal = "TERM"
|
52
|
+
@options = options
|
53
|
+
@first_term_sent = nil
|
52
54
|
@last_checkin = Time.now
|
53
55
|
end
|
54
56
|
|
@@ -105,7 +107,7 @@ module Puma
|
|
105
107
|
|
106
108
|
pid = fork { worker(idx, master) }
|
107
109
|
@cli.debug "Spawned worker: #{pid}"
|
108
|
-
@workers << Worker.new(idx, pid, @phase)
|
110
|
+
@workers << Worker.new(idx, pid, @phase, @options)
|
109
111
|
@options[:after_worker_boot].each { |h| h.call }
|
110
112
|
end
|
111
113
|
|
@@ -180,7 +182,10 @@ module Puma
|
|
180
182
|
end
|
181
183
|
|
182
184
|
def worker(index, master)
|
183
|
-
|
185
|
+
title = "puma: cluster worker #{index}: #{master}"
|
186
|
+
title << " [#{@options[:tag]}]" if @options[:tag]
|
187
|
+
$0 = title
|
188
|
+
|
184
189
|
Signal.trap "SIGINT", "IGNORE"
|
185
190
|
|
186
191
|
@workers = []
|
@@ -267,6 +272,13 @@ module Puma
|
|
267
272
|
wakeup!
|
268
273
|
end
|
269
274
|
|
275
|
+
def reload_worker_directory
|
276
|
+
if dir = @options[:worker_directory]
|
277
|
+
log "+ Changing to #{dir}"
|
278
|
+
Dir.chdir dir
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
270
282
|
def stats
|
271
283
|
%Q!{ "workers": #{@workers.size}, "phase": #{@phase}, "booted_workers": #{@workers.count{|w| w.booted?}} }!
|
272
284
|
end
|
data/lib/puma/configuration.rb
CHANGED
@@ -60,6 +60,14 @@ module Puma
|
|
60
60
|
unless @options[:control_auth_token]
|
61
61
|
setup_random_token
|
62
62
|
end
|
63
|
+
|
64
|
+
unless @options[:tag]
|
65
|
+
@options[:tag] = infer_tag
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def infer_tag
|
70
|
+
File.basename Dir.getwd
|
63
71
|
end
|
64
72
|
|
65
73
|
# Injects the Configuration object into the env
|
@@ -402,6 +410,23 @@ module Puma
|
|
402
410
|
def worker_shutdown_timeout(timeout)
|
403
411
|
@options[:worker_shutdown_timeout] = timeout
|
404
412
|
end
|
413
|
+
|
414
|
+
# When set to true (the default), workers accept all requests
|
415
|
+
# and queue them before passing them to the handlers.
|
416
|
+
# When set to false, each worker process accepts exactly as
|
417
|
+
# many requests as it is configured to simultaneously handle.
|
418
|
+
#
|
419
|
+
# Queueing requests generally improves performance. In some
|
420
|
+
# cases, such as a single threaded application, it may be
|
421
|
+
# better to ensure requests get balanced across workers.
|
422
|
+
#
|
423
|
+
# Note that setting this to false disables HTTP keepalive and
|
424
|
+
# slow clients will occupy a handler thread while the request
|
425
|
+
# is being sent. A reverse proxy, such as nginx, can handle
|
426
|
+
# slow clients and queue requests before they reach puma.
|
427
|
+
def queue_requests(answer=true)
|
428
|
+
@options[:queue_requests] = answer
|
429
|
+
end
|
405
430
|
end
|
406
431
|
end
|
407
432
|
end
|
data/lib/puma/const.rb
CHANGED
@@ -28,8 +28,8 @@ module Puma
|
|
28
28
|
# too taxing on performance.
|
29
29
|
module Const
|
30
30
|
|
31
|
-
PUMA_VERSION = VERSION = "2.
|
32
|
-
CODE_NAME = "
|
31
|
+
PUMA_VERSION = VERSION = "2.11.0".freeze
|
32
|
+
CODE_NAME = "Intrepid Squirrel".freeze
|
33
33
|
|
34
34
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
35
35
|
|
data/lib/puma/control_cli.rb
CHANGED
@@ -7,7 +7,7 @@ require 'socket'
|
|
7
7
|
module Puma
|
8
8
|
class ControlCLI
|
9
9
|
|
10
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop}
|
10
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
|
11
11
|
|
12
12
|
def is_windows?
|
13
13
|
RUBY_PLATFORM =~ /(win|w)32$/ ? true : false
|
@@ -201,6 +201,10 @@ module Puma
|
|
201
201
|
puts "Stats not available via pid only"
|
202
202
|
return
|
203
203
|
|
204
|
+
when "reload-worker-directory"
|
205
|
+
puts "reload-worker-directory not available via pid only"
|
206
|
+
return
|
207
|
+
|
204
208
|
when "phased-restart"
|
205
209
|
Process.kill "SIGUSR1", pid
|
206
210
|
|
data/lib/puma/events.rb
CHANGED
@@ -8,12 +8,24 @@ module Puma
|
|
8
8
|
# The methods available are the events that the Server fires.
|
9
9
|
#
|
10
10
|
class Events
|
11
|
+
class DefaultFormatter
|
12
|
+
def call(str)
|
13
|
+
str
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class PidFormatter
|
18
|
+
def call(str)
|
19
|
+
"[#{$$}] #{str}"
|
20
|
+
end
|
21
|
+
end
|
11
22
|
|
12
23
|
include Const
|
13
24
|
|
14
25
|
# Create an Events object that prints to +stdout+ and +stderr+.
|
15
26
|
#
|
16
27
|
def initialize(stdout, stderr)
|
28
|
+
@formatter = DefaultFormatter.new
|
17
29
|
@stdout = stdout
|
18
30
|
@stderr = stderr
|
19
31
|
|
@@ -28,6 +40,7 @@ module Puma
|
|
28
40
|
end
|
29
41
|
|
30
42
|
attr_reader :stdout, :stderr
|
43
|
+
attr_accessor :formatter
|
31
44
|
|
32
45
|
# Fire callbacks for the named hook
|
33
46
|
#
|
@@ -52,11 +65,11 @@ module Puma
|
|
52
65
|
# Write +str+ to +@stdout+
|
53
66
|
#
|
54
67
|
def log(str)
|
55
|
-
@stdout.puts str
|
68
|
+
@stdout.puts format(str)
|
56
69
|
end
|
57
70
|
|
58
71
|
def write(str)
|
59
|
-
@stdout.write str
|
72
|
+
@stdout.write format(str)
|
60
73
|
end
|
61
74
|
|
62
75
|
def debug(str)
|
@@ -66,10 +79,14 @@ module Puma
|
|
66
79
|
# Write +str+ to +@stderr+
|
67
80
|
#
|
68
81
|
def error(str)
|
69
|
-
@stderr.puts "ERROR: #{str}"
|
82
|
+
@stderr.puts format("ERROR: #{str}")
|
70
83
|
exit 1
|
71
84
|
end
|
72
85
|
|
86
|
+
def format(str)
|
87
|
+
formatter.call(str)
|
88
|
+
end
|
89
|
+
|
73
90
|
# An HTTP parse error has occured.
|
74
91
|
# +server+ is the Server object, +env+ the request, and +error+ a
|
75
92
|
# parsing exception.
|
@@ -113,18 +130,4 @@ module Puma
|
|
113
130
|
Events.new $stdout, $stderr
|
114
131
|
end
|
115
132
|
end
|
116
|
-
|
117
|
-
class PidEvents < Events
|
118
|
-
def log(str)
|
119
|
-
super "[#{$$}] #{str}"
|
120
|
-
end
|
121
|
-
|
122
|
-
def write(str)
|
123
|
-
super "[#{$$}] #{str}"
|
124
|
-
end
|
125
|
-
|
126
|
-
def error(str)
|
127
|
-
super "[#{$$}] #{str}"
|
128
|
-
end
|
129
|
-
end
|
130
133
|
end
|
data/lib/puma/server.rb
CHANGED
@@ -74,6 +74,7 @@ module Puma
|
|
74
74
|
@leak_stack_on_error = true
|
75
75
|
|
76
76
|
@options = options
|
77
|
+
@queue_requests = options[:queue_requests].nil? ? true : options[:queue_requests]
|
77
78
|
|
78
79
|
ENV['RACK_ENV'] ||= "development"
|
79
80
|
|
@@ -235,13 +236,20 @@ module Puma
|
|
235
236
|
return run_lopez_mode(background)
|
236
237
|
end
|
237
238
|
|
239
|
+
queue_requests = @queue_requests
|
240
|
+
|
238
241
|
@thread_pool = ThreadPool.new(@min_threads,
|
239
242
|
@max_threads,
|
240
243
|
IOBuffer) do |client, buffer|
|
241
244
|
process_now = false
|
242
245
|
|
243
246
|
begin
|
244
|
-
|
247
|
+
if queue_requests
|
248
|
+
process_now = client.eagerly_finish
|
249
|
+
else
|
250
|
+
client.finish
|
251
|
+
process_now = true
|
252
|
+
end
|
245
253
|
rescue HttpParserError => e
|
246
254
|
client.write_400
|
247
255
|
client.close
|
@@ -261,9 +269,10 @@ module Puma
|
|
261
269
|
|
262
270
|
@thread_pool.clean_thread_locals = @options[:clean_thread_locals]
|
263
271
|
|
264
|
-
|
265
|
-
|
266
|
-
|
272
|
+
if queue_requests
|
273
|
+
@reactor = Reactor.new self, @thread_pool
|
274
|
+
@reactor.run_in_thread
|
275
|
+
end
|
267
276
|
|
268
277
|
if @auto_trim_time
|
269
278
|
@thread_pool.auto_trim!(@auto_trim_time)
|
@@ -284,6 +293,7 @@ module Puma
|
|
284
293
|
check = @check
|
285
294
|
sockets = [check] + @binder.ios
|
286
295
|
pool = @thread_pool
|
296
|
+
queue_requests = @queue_requests
|
287
297
|
|
288
298
|
while @status == :run
|
289
299
|
begin
|
@@ -296,6 +306,7 @@ module Puma
|
|
296
306
|
if io = sock.accept_nonblock
|
297
307
|
client = Client.new io, @binder.env(sock)
|
298
308
|
pool << client
|
309
|
+
pool.wait_until_not_full unless queue_requests
|
299
310
|
end
|
300
311
|
rescue SystemCallError
|
301
312
|
end
|
@@ -312,9 +323,10 @@ module Puma
|
|
312
323
|
@events.fire :state, @status
|
313
324
|
|
314
325
|
graceful_shutdown if @status == :stop || @status == :restart
|
315
|
-
|
316
|
-
|
317
|
-
|
326
|
+
if queue_requests
|
327
|
+
@reactor.clear! if @status == :restart
|
328
|
+
@reactor.shutdown
|
329
|
+
end
|
318
330
|
rescue Exception => e
|
319
331
|
STDERR.puts "Exception handling servers: #{e.message} (#{e.class})"
|
320
332
|
STDERR.puts e.backtrace
|
@@ -367,6 +379,7 @@ module Puma
|
|
367
379
|
close_socket = false
|
368
380
|
return
|
369
381
|
when true
|
382
|
+
return unless @queue_requests
|
370
383
|
buffer.reset
|
371
384
|
|
372
385
|
unless client.reset(@status == :run)
|
@@ -443,12 +456,14 @@ module Puma
|
|
443
456
|
# intermediary acting on behalf of the actual source client."
|
444
457
|
#
|
445
458
|
|
446
|
-
|
459
|
+
unless env.key?(REMOTE_ADDR)
|
460
|
+
addr = client.peeraddr.last
|
447
461
|
|
448
|
-
|
449
|
-
|
462
|
+
# Set unix socket addrs to localhost
|
463
|
+
addr = "127.0.0.1" if addr.empty?
|
450
464
|
|
451
|
-
|
465
|
+
env[REMOTE_ADDR] = addr
|
466
|
+
end
|
452
467
|
end
|
453
468
|
|
454
469
|
def default_server_port(env)
|
@@ -716,7 +731,7 @@ module Puma
|
|
716
731
|
if @leak_stack_on_error
|
717
732
|
[500, {}, ["Puma caught this error: #{e.message} (#{e.class})\n#{e.backtrace.join("\n")}"]]
|
718
733
|
else
|
719
|
-
[500, {}, ["
|
734
|
+
[500, {}, ["An unhandled lowlevel error occured. The application logs may have details.\n"]]
|
720
735
|
end
|
721
736
|
end
|
722
737
|
|
data/lib/puma/single.rb
CHANGED
@@ -73,6 +73,7 @@ module Puma
|
|
73
73
|
if daemon?
|
74
74
|
log "* Daemonizing..."
|
75
75
|
Process.daemon(true)
|
76
|
+
redirect_io
|
76
77
|
end
|
77
78
|
|
78
79
|
load_and_bind
|
@@ -84,12 +85,11 @@ module Puma
|
|
84
85
|
|
85
86
|
@server = server = start_server
|
86
87
|
|
87
|
-
unless
|
88
|
+
unless daemon?
|
88
89
|
log "Use Ctrl-C to stop"
|
90
|
+
redirect_io
|
89
91
|
end
|
90
92
|
|
91
|
-
redirect_io
|
92
|
-
|
93
93
|
@cli.events.fire_on_booted!
|
94
94
|
|
95
95
|
begin
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -12,7 +12,8 @@ module Puma
|
|
12
12
|
# thread.
|
13
13
|
#
|
14
14
|
def initialize(min, max, *extra, &block)
|
15
|
-
@
|
15
|
+
@not_empty = ConditionVariable.new
|
16
|
+
@not_full = ConditionVariable.new
|
16
17
|
@mutex = Mutex.new
|
17
18
|
|
18
19
|
@todo = []
|
@@ -60,7 +61,8 @@ module Puma
|
|
60
61
|
todo = @todo
|
61
62
|
block = @block
|
62
63
|
mutex = @mutex
|
63
|
-
|
64
|
+
not_empty = @not_empty
|
65
|
+
not_full = @not_full
|
64
66
|
|
65
67
|
extra = @extra.map { |i| i.new }
|
66
68
|
|
@@ -83,7 +85,8 @@ module Puma
|
|
83
85
|
end
|
84
86
|
|
85
87
|
@waiting += 1
|
86
|
-
|
88
|
+
not_full.signal
|
89
|
+
not_empty.wait mutex
|
87
90
|
@waiting -= 1
|
88
91
|
end
|
89
92
|
|
@@ -127,7 +130,15 @@ module Puma
|
|
127
130
|
spawn_thread
|
128
131
|
end
|
129
132
|
|
130
|
-
@
|
133
|
+
@not_empty.signal
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def wait_until_not_full
|
138
|
+
@mutex.synchronize do
|
139
|
+
until @todo.size - @waiting < @max - @spawned or @shutdown
|
140
|
+
@not_full.wait @mutex
|
141
|
+
end
|
131
142
|
end
|
132
143
|
end
|
133
144
|
|
@@ -139,7 +150,7 @@ module Puma
|
|
139
150
|
@mutex.synchronize do
|
140
151
|
if (force or @waiting > 0) and @spawned - @trim_requested > @min
|
141
152
|
@trim_requested += 1
|
142
|
-
@
|
153
|
+
@not_empty.signal
|
143
154
|
end
|
144
155
|
end
|
145
156
|
end
|
@@ -178,7 +189,8 @@ module Puma
|
|
178
189
|
def shutdown
|
179
190
|
@mutex.synchronize do
|
180
191
|
@shutdown = true
|
181
|
-
@
|
192
|
+
@not_empty.broadcast
|
193
|
+
@not_full.broadcast
|
182
194
|
|
183
195
|
@auto_trim.stop if @auto_trim
|
184
196
|
end
|
data/lib/rack/handler/puma.rb
CHANGED
data/test/test_integration.rb
CHANGED
@@ -102,6 +102,47 @@ class TestIntegration < Test::Unit::TestCase
|
|
102
102
|
assert_kind_of Thread, t.join(1), "server didn't stop"
|
103
103
|
end
|
104
104
|
|
105
|
+
def notest_phased_restart_via_pumactl
|
106
|
+
if defined?(JRUBY_VERSION) || RbConfig::CONFIG["host_os"] =~ /mingw|mswin/
|
107
|
+
assert true
|
108
|
+
return
|
109
|
+
end
|
110
|
+
|
111
|
+
cli = Puma::CLI.new %W!-q -S #{@state_path} -b unix://#{@bind_path} --control unix://#{@control_path} -w 2 test/hello-stuck.ru!, @events
|
112
|
+
cli.options[:worker_shutdown_timeout] = 1
|
113
|
+
|
114
|
+
t = Thread.new do
|
115
|
+
cli.run
|
116
|
+
end
|
117
|
+
|
118
|
+
wait_booted
|
119
|
+
|
120
|
+
# Make both workers stuck
|
121
|
+
s1 = UNIXSocket.new @bind_path
|
122
|
+
s1 << "GET / HTTP/1.0\r\n\r\n"
|
123
|
+
s2 = UNIXSocket.new @bind_path
|
124
|
+
s2 << "GET / HTTP/1.0\r\n\r\n"
|
125
|
+
|
126
|
+
sout = StringIO.new
|
127
|
+
|
128
|
+
# Phased restart
|
129
|
+
ccli = Puma::ControlCLI.new %W!-S #{@state_path} phased-restart!, sout
|
130
|
+
ccli.run
|
131
|
+
sleep 20
|
132
|
+
@events.stdout.rewind
|
133
|
+
log = @events.stdout.readlines.join("")
|
134
|
+
assert_match(/TERM sent/, log)
|
135
|
+
assert_match(/KILL sent/, log)
|
136
|
+
assert_match(/Worker 0 \(pid: \d+\) booted, phase: 1/, log)
|
137
|
+
assert_match(/Worker 1 \(pid: \d+\) booted, phase: 1/, log)
|
138
|
+
|
139
|
+
# Stop
|
140
|
+
ccli = Puma::ControlCLI.new %W!-S #{@state_path} stop!, sout
|
141
|
+
ccli.run
|
142
|
+
|
143
|
+
assert_kind_of Thread, t.join(5), "server didn't stop"
|
144
|
+
end
|
145
|
+
|
105
146
|
def notest_restart_closes_keepalive_sockets
|
106
147
|
server("-q test/hello.ru")
|
107
148
|
|
data/tools/jungle/init.d/puma
CHANGED
@@ -47,7 +47,8 @@ do_start() {
|
|
47
47
|
if [ "$log_file" = "" ]; then
|
48
48
|
log_file="$dir/log/puma.log"
|
49
49
|
fi
|
50
|
-
|
50
|
+
environment=`echo $i | cut -d , -f 5`
|
51
|
+
do_start_one $dir $user $config_file $log_file $environment
|
51
52
|
done
|
52
53
|
}
|
53
54
|
|
@@ -57,12 +58,12 @@ do_start_one() {
|
|
57
58
|
PID=`cat $PIDFILE`
|
58
59
|
# If the puma isn't running, run it, otherwise restart it.
|
59
60
|
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
|
60
|
-
do_start_one_do $1 $2 $3 $4
|
61
|
+
do_start_one_do $1 $2 $3 $4 $5
|
61
62
|
else
|
62
63
|
do_restart_one $1
|
63
64
|
fi
|
64
65
|
else
|
65
|
-
do_start_one_do $1 $2 $3 $4
|
66
|
+
do_start_one_do $1 $2 $3 $4 $5
|
66
67
|
fi
|
67
68
|
}
|
68
69
|
|
@@ -70,6 +71,14 @@ do_start_one_do() {
|
|
70
71
|
log_daemon_msg "--> Woke up puma $1"
|
71
72
|
log_daemon_msg "user $2"
|
72
73
|
log_daemon_msg "log to $4"
|
74
|
+
|
75
|
+
if [ ! -z "$5" ]; then
|
76
|
+
for e in $(echo "$5" | tr ';' '\n'); do
|
77
|
+
log_daemon_msg "environment $e"
|
78
|
+
v=${e%%\=*} ; eval "$e" ; export $v
|
79
|
+
done
|
80
|
+
fi
|
81
|
+
|
73
82
|
start-stop-daemon --verbose --start --chdir $1 --chuid $2 --background --exec $RUNPUMA -- $1 $3 $4
|
74
83
|
}
|
75
84
|
|
@@ -140,7 +149,8 @@ do_restart_one() {
|
|
140
149
|
if [ "$log_file" = "" ]; then
|
141
150
|
log_file="$dir/log/puma.log"
|
142
151
|
fi
|
143
|
-
|
152
|
+
environment=`echo $i | cut -d , -f 5`
|
153
|
+
do_start_one $dir $user $config_file $log_file $environment
|
144
154
|
fi
|
145
155
|
return 0
|
146
156
|
}
|
@@ -209,6 +219,11 @@ do_add() {
|
|
209
219
|
str="$str,$4"
|
210
220
|
fi
|
211
221
|
|
222
|
+
# Environment variables
|
223
|
+
if [ "$5" != "" ]; then
|
224
|
+
str="$str,$5"
|
225
|
+
fi
|
226
|
+
|
212
227
|
# Add it to the jungle
|
213
228
|
echo $str >> $CONFIG
|
214
229
|
log_daemon_msg "Added a Puma to the jungle: $str. You still have to start it though."
|
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: 2.
|
4
|
+
version: 2.11.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:
|
11
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -64,14 +64,14 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '3.
|
67
|
+
version: '3.13'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '3.
|
74
|
+
version: '3.13'
|
75
75
|
description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
|
76
76
|
for Ruby/Rack applications. Puma is intended for use in both development and production
|
77
77
|
environments. In order to get the best throughput, it is highly recommended that
|