puma 2.3.0 → 2.3.1
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/Gemfile +1 -0
- data/History.txt +10 -0
- data/Manifest.txt +5 -0
- data/README.md +8 -0
- data/Rakefile +3 -0
- data/lib/puma/cli.rb +20 -0
- data/lib/puma/cluster.rb +313 -0
- data/lib/puma/const.rb +1 -1
- data/lib/puma/runner.rb +90 -0
- data/lib/puma/single.rb +88 -0
- data/puma.gemspec +3 -3
- data/tools/jungle/README.md +9 -0
- data/tools/trickletest.rb +45 -0
- metadata +7 -1
data/Gemfile
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 2.3.1 / 2013-07-06
|
2
|
+
|
3
|
+
* 2 bug fixes:
|
4
|
+
|
5
|
+
* Include the right files in the Manifest.
|
6
|
+
* Disable inheriting connections on restart on windows. Fixes #166
|
7
|
+
|
8
|
+
* 1 doc change:
|
9
|
+
* Better document some platform constraints
|
10
|
+
|
1
11
|
=== 2.3.0 / 2013-07-05
|
2
12
|
|
3
13
|
* 1 major bug fix:
|
data/Manifest.txt
CHANGED
@@ -31,6 +31,7 @@ lib/puma/binder.rb
|
|
31
31
|
lib/puma/capistrano.rb
|
32
32
|
lib/puma/cli.rb
|
33
33
|
lib/puma/client.rb
|
34
|
+
lib/puma/cluster.rb
|
34
35
|
lib/puma/compat.rb
|
35
36
|
lib/puma/configuration.rb
|
36
37
|
lib/puma/const.rb
|
@@ -47,14 +48,18 @@ lib/puma/null_io.rb
|
|
47
48
|
lib/puma/rack_default.rb
|
48
49
|
lib/puma/rack_patch.rb
|
49
50
|
lib/puma/reactor.rb
|
51
|
+
lib/puma/runner.rb
|
50
52
|
lib/puma/server.rb
|
53
|
+
lib/puma/single.rb
|
51
54
|
lib/puma/thread_pool.rb
|
52
55
|
lib/puma/util.rb
|
53
56
|
lib/rack/handler/puma.rb
|
54
57
|
puma.gemspec
|
58
|
+
tools/jungle/README.md
|
55
59
|
tools/jungle/init.d/README.md
|
56
60
|
tools/jungle/init.d/puma
|
57
61
|
tools/jungle/init.d/run-puma
|
58
62
|
tools/jungle/upstart/README.md
|
59
63
|
tools/jungle/upstart/puma-manager.conf
|
60
64
|
tools/jungle/upstart/puma.conf
|
65
|
+
tools/trickletest.rb
|
data/README.md
CHANGED
@@ -175,6 +175,14 @@ Puma isn't able to understand all the resources that your app may use, so it pro
|
|
175
175
|
|
176
176
|
You should place code to close global log files, redis connections, etc in this block so that their file descriptors don't leak into the restarted process. Failure to do so will result in slowly running out of descriptors and eventually obscure crashes as the server is restart many times.
|
177
177
|
|
178
|
+
### Platform Constaints
|
179
|
+
|
180
|
+
Because of various platforms not being implement certain things, the following differences occur when puma is used on different platforms:
|
181
|
+
|
182
|
+
* On JRuby and Windows, server sockets are not seamless on restart, they must be closed and reopened. These platforms have no way to pass descriptors into a new process that is exposed to ruby.
|
183
|
+
* On Windows, daemon mode is not supported due to a lack of fork(2).
|
184
|
+
* On JRuby and Windows, cluster mode is not supported due to a lack of fork(2).
|
185
|
+
|
178
186
|
## pumactl
|
179
187
|
|
180
188
|
If you start puma with `-S some/path` then you can pass that same path to the `pumactl` program to control your server. For instance:
|
data/Rakefile
CHANGED
@@ -5,6 +5,7 @@ require "rake/javaextensiontask"
|
|
5
5
|
IS_JRUBY = defined?(RUBY_ENGINE) ? RUBY_ENGINE == "jruby" : false
|
6
6
|
|
7
7
|
Hoe.plugin :git
|
8
|
+
Hoe.plugin :ignore
|
8
9
|
|
9
10
|
HOE = Hoe.spec "puma" do
|
10
11
|
self.rubyforge_name = 'puma'
|
@@ -24,6 +25,8 @@ HOE = Hoe.spec "puma" do
|
|
24
25
|
extra_dev_deps << ["rake-compiler", "~> 0.8.0"]
|
25
26
|
end
|
26
27
|
|
28
|
+
task :prerelease => [:clobber, :check_manifest, :test]
|
29
|
+
|
27
30
|
# hoe/test and rake-compiler don't seem to play well together, so disable
|
28
31
|
# hoe/test's .gemtest touch file thingy for now
|
29
32
|
HOE.spec.files -= [".gemtest"]
|
data/lib/puma/cli.rb
CHANGED
@@ -365,6 +365,26 @@ module Puma
|
|
365
365
|
|
366
366
|
require 'puma/jruby_restart'
|
367
367
|
JRubyRestart.chdir_exec(@restart_dir, restart_args)
|
368
|
+
|
369
|
+
elsif windows?
|
370
|
+
@binder.listeners.each_with_index do |(str,io),i|
|
371
|
+
io.close
|
372
|
+
|
373
|
+
# We have to unlink a unix socket path that's not being used
|
374
|
+
uri = URI.parse str
|
375
|
+
if uri.scheme == "unix"
|
376
|
+
path = "#{uri.host}#{uri.path}"
|
377
|
+
File.unlink path
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
argv = restart_args
|
382
|
+
|
383
|
+
Dir.chdir @restart_dir
|
384
|
+
|
385
|
+
argv += [redirects] unless RUBY_VERSION < '1.9'
|
386
|
+
Kernel.exec(*argv)
|
387
|
+
|
368
388
|
else
|
369
389
|
redirects = {:close_others => true}
|
370
390
|
@binder.listeners.each_with_index do |(l,io),i|
|
data/lib/puma/cluster.rb
ADDED
@@ -0,0 +1,313 @@
|
|
1
|
+
require 'puma/runner'
|
2
|
+
|
3
|
+
module Puma
|
4
|
+
class Cluster < Runner
|
5
|
+
def initialize(cli)
|
6
|
+
super cli
|
7
|
+
|
8
|
+
@phase = 0
|
9
|
+
@workers = []
|
10
|
+
|
11
|
+
@phased_state = :idle
|
12
|
+
@phased_restart = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop_workers
|
16
|
+
log "- Gracefully shutting down workers..."
|
17
|
+
@workers.each { |x| x.term }
|
18
|
+
|
19
|
+
begin
|
20
|
+
Process.waitall
|
21
|
+
rescue Interrupt
|
22
|
+
log "! Cancelled waiting for workers"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def start_phased_restart
|
27
|
+
@phase += 1
|
28
|
+
log "- Starting phased worker restart, phase: #{@phase}"
|
29
|
+
end
|
30
|
+
|
31
|
+
class Worker
|
32
|
+
def initialize(pid, phase)
|
33
|
+
@pid = pid
|
34
|
+
@phase = phase
|
35
|
+
@stage = :started
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :pid, :phase
|
39
|
+
|
40
|
+
def booted?
|
41
|
+
@stage == :booted
|
42
|
+
end
|
43
|
+
|
44
|
+
def boot!
|
45
|
+
@stage = :booted
|
46
|
+
end
|
47
|
+
|
48
|
+
def term
|
49
|
+
begin
|
50
|
+
Process.kill "TERM", @pid
|
51
|
+
rescue Errno::ESRCH
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def spawn_workers
|
57
|
+
diff = @options[:workers] - @workers.size
|
58
|
+
|
59
|
+
upgrade = (@phased_state == :waiting)
|
60
|
+
|
61
|
+
master = Process.pid
|
62
|
+
|
63
|
+
diff.times do
|
64
|
+
pid = fork { worker(upgrade, master) }
|
65
|
+
@cli.debug "Spawned worker: #{pid}"
|
66
|
+
@workers << Worker.new(pid, @phase)
|
67
|
+
end
|
68
|
+
|
69
|
+
if diff > 0
|
70
|
+
@phased_state = :idle
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def all_workers_booted?
|
75
|
+
@workers.count { |w| !w.booted? } == 0
|
76
|
+
end
|
77
|
+
|
78
|
+
def check_workers
|
79
|
+
while @workers.any?
|
80
|
+
pid = Process.waitpid(-1, Process::WNOHANG)
|
81
|
+
break unless pid
|
82
|
+
|
83
|
+
@workers.delete_if { |w| w.pid == pid }
|
84
|
+
end
|
85
|
+
|
86
|
+
spawn_workers
|
87
|
+
|
88
|
+
if @phased_state == :idle && all_workers_booted?
|
89
|
+
# If we're running at proper capacity, check to see if
|
90
|
+
# we need to phase any workers out (which will restart
|
91
|
+
# in the right phase).
|
92
|
+
#
|
93
|
+
w = @workers.find { |x| x.phase != @phase }
|
94
|
+
|
95
|
+
if w
|
96
|
+
@phased_state = :waiting
|
97
|
+
log "- Stopping #{w.pid} for phased upgrade..."
|
98
|
+
w.term
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def wakeup!
|
104
|
+
begin
|
105
|
+
@wakeup.write "!" unless @wakeup.closed?
|
106
|
+
rescue SystemCallError, IOError
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def worker(upgrade, master)
|
111
|
+
$0 = "puma: cluster worker: #{master}"
|
112
|
+
Signal.trap "SIGINT", "IGNORE"
|
113
|
+
|
114
|
+
@master_read.close
|
115
|
+
@suicide_pipe.close
|
116
|
+
|
117
|
+
Thread.new do
|
118
|
+
IO.select [@check_pipe]
|
119
|
+
log "! Detected parent died, dying"
|
120
|
+
exit! 1
|
121
|
+
end
|
122
|
+
|
123
|
+
# Be sure to change the directory again before loading
|
124
|
+
# the app. This way we can pick up new code.
|
125
|
+
if upgrade
|
126
|
+
if dir = @options[:worker_directory]
|
127
|
+
log "+ Changing to #{dir}"
|
128
|
+
Dir.chdir dir
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Invoke any worker boot hooks so they can get
|
133
|
+
# things in shape before booting the app.
|
134
|
+
hooks = @options[:worker_boot]
|
135
|
+
hooks.each { |h| h.call }
|
136
|
+
|
137
|
+
server = start_server
|
138
|
+
|
139
|
+
Signal.trap "SIGTERM" do
|
140
|
+
server.stop
|
141
|
+
end
|
142
|
+
|
143
|
+
begin
|
144
|
+
@worker_write << "b#{Process.pid}\n"
|
145
|
+
rescue SystemCallError, IOError
|
146
|
+
STDERR.puts "Master seems to have exitted, exitting."
|
147
|
+
return
|
148
|
+
end
|
149
|
+
|
150
|
+
server.run.join
|
151
|
+
|
152
|
+
ensure
|
153
|
+
@worker_write.close
|
154
|
+
end
|
155
|
+
|
156
|
+
def restart
|
157
|
+
@restart = true
|
158
|
+
stop
|
159
|
+
end
|
160
|
+
|
161
|
+
def phased_restart
|
162
|
+
return false if @options[:preload_app]
|
163
|
+
|
164
|
+
@phased_restart = true
|
165
|
+
wakeup!
|
166
|
+
|
167
|
+
true
|
168
|
+
end
|
169
|
+
|
170
|
+
def stop
|
171
|
+
@status = :stop
|
172
|
+
wakeup!
|
173
|
+
end
|
174
|
+
|
175
|
+
def stop_blocked
|
176
|
+
@status = :stop if @status == :run
|
177
|
+
wakeup!
|
178
|
+
Process.waitall
|
179
|
+
end
|
180
|
+
|
181
|
+
def halt
|
182
|
+
@status = :halt
|
183
|
+
wakeup!
|
184
|
+
end
|
185
|
+
|
186
|
+
def stats
|
187
|
+
%Q!{ "workers": #{@workers.size}, "phase": #{@phase} }!
|
188
|
+
end
|
189
|
+
|
190
|
+
def preload?
|
191
|
+
@options[:preload_app]
|
192
|
+
end
|
193
|
+
|
194
|
+
def run
|
195
|
+
@status = :run
|
196
|
+
|
197
|
+
output_header "cluster"
|
198
|
+
|
199
|
+
log "* Process workers: #{@options[:workers]}"
|
200
|
+
|
201
|
+
if preload?
|
202
|
+
log "* Preloading application"
|
203
|
+
load_and_bind
|
204
|
+
else
|
205
|
+
log "* Phased restart available"
|
206
|
+
|
207
|
+
unless @cli.config.app_configured?
|
208
|
+
error "No application configured, nothing to run"
|
209
|
+
exit 1
|
210
|
+
end
|
211
|
+
|
212
|
+
@cli.binder.parse @options[:binds], self
|
213
|
+
end
|
214
|
+
|
215
|
+
read, @wakeup = Puma::Util.pipe
|
216
|
+
|
217
|
+
Signal.trap "SIGCHLD" do
|
218
|
+
wakeup!
|
219
|
+
end
|
220
|
+
|
221
|
+
master_pid = Process.pid
|
222
|
+
|
223
|
+
Signal.trap "SIGTERM" do
|
224
|
+
# The worker installs their own SIGTERM when booted.
|
225
|
+
# Until then, this is run by the worker and the worker
|
226
|
+
# should just exit if they get it.
|
227
|
+
if Process.pid != master_pid
|
228
|
+
log "Early termination of worker"
|
229
|
+
exit! 0
|
230
|
+
else
|
231
|
+
stop
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
if preload?
|
236
|
+
Signal.trap "SIGUSR1" do
|
237
|
+
log "App preloaded, phased restart unavailable"
|
238
|
+
end
|
239
|
+
else
|
240
|
+
Signal.trap "SIGUSR1" do
|
241
|
+
phased_restart
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Used by the workers to detect if the master process dies.
|
246
|
+
# If select says that @check_pipe is ready, it's because the
|
247
|
+
# master has exited and @suicide_pipe has been automatically
|
248
|
+
# closed.
|
249
|
+
#
|
250
|
+
@check_pipe, @suicide_pipe = Puma::Util.pipe
|
251
|
+
|
252
|
+
if daemon?
|
253
|
+
log "* Daemonizing..."
|
254
|
+
Process.daemon(true)
|
255
|
+
else
|
256
|
+
log "Use Ctrl-C to stop"
|
257
|
+
end
|
258
|
+
|
259
|
+
redirect_io
|
260
|
+
|
261
|
+
@cli.write_state
|
262
|
+
|
263
|
+
@master_read, @worker_write = read, @wakeup
|
264
|
+
spawn_workers
|
265
|
+
|
266
|
+
Signal.trap "SIGINT" do
|
267
|
+
stop
|
268
|
+
end
|
269
|
+
|
270
|
+
@cli.events.fire_on_booted!
|
271
|
+
|
272
|
+
begin
|
273
|
+
while @status == :run
|
274
|
+
begin
|
275
|
+
res = IO.select([read], nil, nil, 5)
|
276
|
+
|
277
|
+
if res
|
278
|
+
req = read.read_nonblock(1)
|
279
|
+
|
280
|
+
if req == "b"
|
281
|
+
pid = read.gets.to_i
|
282
|
+
w = @workers.find { |x| x.pid == pid }
|
283
|
+
if w
|
284
|
+
w.boot!
|
285
|
+
log "- Worker #{pid} booted, phase: #{w.phase}"
|
286
|
+
else
|
287
|
+
log "! Out-of-sync worker list, no #{pid} worker"
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
if @phased_restart
|
293
|
+
start_phased_restart
|
294
|
+
@phased_restart = false
|
295
|
+
end
|
296
|
+
|
297
|
+
check_workers
|
298
|
+
|
299
|
+
rescue Interrupt
|
300
|
+
@status = :stop
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
stop_workers unless @status == :halt
|
305
|
+
ensure
|
306
|
+
@check_pipe.close
|
307
|
+
@suicide_pipe.close
|
308
|
+
read.close
|
309
|
+
@wakeup.close
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
data/lib/puma/const.rb
CHANGED
data/lib/puma/runner.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module Puma
|
2
|
+
class Runner
|
3
|
+
def initialize(cli)
|
4
|
+
@cli = cli
|
5
|
+
@options = cli.options
|
6
|
+
@app = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def daemon?
|
10
|
+
@options[:daemon]
|
11
|
+
end
|
12
|
+
|
13
|
+
def development?
|
14
|
+
@options[:environment] == "development"
|
15
|
+
end
|
16
|
+
|
17
|
+
def log(str)
|
18
|
+
@cli.log str
|
19
|
+
end
|
20
|
+
|
21
|
+
def error(str)
|
22
|
+
@cli.error str
|
23
|
+
end
|
24
|
+
|
25
|
+
def output_header(mode)
|
26
|
+
min_t = @options[:min_threads]
|
27
|
+
max_t = @options[:max_threads]
|
28
|
+
|
29
|
+
log "Puma starting in #{mode} mode..."
|
30
|
+
log "* Version #{Puma::Const::PUMA_VERSION}, codename: #{Puma::Const::CODE_NAME}"
|
31
|
+
log "* Min threads: #{min_t}, max threads: #{max_t}"
|
32
|
+
log "* Environment: #{ENV['RACK_ENV']}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def redirect_io
|
36
|
+
stdout = @options[:redirect_stdout]
|
37
|
+
stderr = @options[:redirect_stderr]
|
38
|
+
append = @options[:redirect_append]
|
39
|
+
|
40
|
+
if stdout
|
41
|
+
STDOUT.reopen stdout, (append ? "a" : "w")
|
42
|
+
STDOUT.sync = true
|
43
|
+
STDOUT.puts "=== puma startup: #{Time.now} ==="
|
44
|
+
end
|
45
|
+
|
46
|
+
if stderr
|
47
|
+
STDERR.reopen stderr, (append ? "a" : "w")
|
48
|
+
STDERR.sync = true
|
49
|
+
STDERR.puts "=== puma startup: #{Time.now} ==="
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def load_and_bind
|
54
|
+
unless @cli.config.app_configured?
|
55
|
+
error "No application configured, nothing to run"
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
# Load the app before we daemonize.
|
60
|
+
begin
|
61
|
+
@app = @cli.config.app
|
62
|
+
rescue Exception => e
|
63
|
+
log "! Unable to load application"
|
64
|
+
raise e
|
65
|
+
end
|
66
|
+
|
67
|
+
@cli.binder.parse @options[:binds], self
|
68
|
+
end
|
69
|
+
|
70
|
+
def app
|
71
|
+
@app ||= @cli.config.app
|
72
|
+
end
|
73
|
+
|
74
|
+
def start_server
|
75
|
+
min_t = @options[:min_threads]
|
76
|
+
max_t = @options[:max_threads]
|
77
|
+
|
78
|
+
server = Puma::Server.new app, @cli.events
|
79
|
+
server.min_threads = min_t
|
80
|
+
server.max_threads = max_t
|
81
|
+
server.inherit_binder @cli.binder
|
82
|
+
|
83
|
+
unless development?
|
84
|
+
server.leak_stack_on_error = false
|
85
|
+
end
|
86
|
+
|
87
|
+
server
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/puma/single.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'puma/runner'
|
2
|
+
|
3
|
+
module Puma
|
4
|
+
class Single < Runner
|
5
|
+
def stats
|
6
|
+
b = @server.backlog
|
7
|
+
r = @server.running
|
8
|
+
%Q!{ "backlog": #{b}, "running": #{r} }!
|
9
|
+
end
|
10
|
+
|
11
|
+
def restart
|
12
|
+
@server.begin_restart
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop
|
16
|
+
@server.stop false
|
17
|
+
end
|
18
|
+
|
19
|
+
def halt
|
20
|
+
@server.halt
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop_blocked
|
24
|
+
log "- Gracefully stopping, waiting for requests to finish"
|
25
|
+
@server.stop(true)
|
26
|
+
end
|
27
|
+
|
28
|
+
def jruby_daemon?
|
29
|
+
daemon? and @cli.jruby?
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
already_daemon = false
|
34
|
+
|
35
|
+
if jruby_daemon?
|
36
|
+
require 'puma/jruby_restart'
|
37
|
+
|
38
|
+
if JRubyRestart.daemon?
|
39
|
+
# load and bind before redirecting IO so errors show up on stdout/stderr
|
40
|
+
load_and_bind
|
41
|
+
end
|
42
|
+
|
43
|
+
already_daemon = JRubyRestart.daemon_init
|
44
|
+
end
|
45
|
+
|
46
|
+
output_header "single"
|
47
|
+
|
48
|
+
if jruby_daemon?
|
49
|
+
unless already_daemon
|
50
|
+
pid = nil
|
51
|
+
|
52
|
+
Signal.trap "SIGUSR2" do
|
53
|
+
log "* Started new process #{pid} as daemon..."
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
pid = @cli.jruby_daemon_start
|
58
|
+
sleep
|
59
|
+
end
|
60
|
+
else
|
61
|
+
load_and_bind
|
62
|
+
|
63
|
+
if daemon?
|
64
|
+
log "* Daemonizing..."
|
65
|
+
Process.daemon(true)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
@cli.write_state
|
70
|
+
|
71
|
+
@server = server = start_server
|
72
|
+
|
73
|
+
unless @options[:daemon]
|
74
|
+
log "Use Ctrl-C to stop"
|
75
|
+
end
|
76
|
+
|
77
|
+
redirect_io
|
78
|
+
|
79
|
+
@cli.events.fire_on_booted!
|
80
|
+
|
81
|
+
begin
|
82
|
+
server.run.join
|
83
|
+
rescue Interrupt
|
84
|
+
# Swallow it
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/puma.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "puma"
|
5
|
-
s.version = "2.3.
|
5
|
+
s.version = "2.3.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Evan Phoenix"]
|
@@ -11,8 +11,8 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.email = ["evan@phx.io"]
|
12
12
|
s.executables = ["puma", "pumactl"]
|
13
13
|
s.extensions = ["ext/puma_http11/extconf.rb"]
|
14
|
-
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.md", "docs/config.md", "docs/nginx.md", "tools/jungle/init.d/README.md", "tools/jungle/upstart/README.md"]
|
15
|
-
s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "docs/config.md", "docs/nginx.md", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/io_buffer.c", "ext/puma_http11/mini_ssl.c", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/org/jruby/puma/MiniSSL.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/accept_nonblock.rb", "lib/puma/app/status.rb", "lib/puma/binder.rb", "lib/puma/capistrano.rb", "lib/puma/cli.rb", "lib/puma/client.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/daemon_ext.rb", "lib/puma/delegation.rb", "lib/puma/detect.rb", "lib/puma/events.rb", "lib/puma/io_buffer.rb", "lib/puma/java_io_buffer.rb", "lib/puma/jruby_restart.rb", "lib/puma/minissl.rb", "lib/puma/null_io.rb", "lib/puma/rack_default.rb", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/puma/util.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "tools/jungle/init.d/README.md", "tools/jungle/init.d/puma", "tools/jungle/init.d/run-puma", "tools/jungle/upstart/README.md", "tools/jungle/upstart/puma-manager.conf", "tools/jungle/upstart/puma.conf", "test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_minissl.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
|
14
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.md", "docs/config.md", "docs/nginx.md", "tools/jungle/README.md", "tools/jungle/init.d/README.md", "tools/jungle/upstart/README.md"]
|
15
|
+
s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "docs/config.md", "docs/nginx.md", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/io_buffer.c", "ext/puma_http11/mini_ssl.c", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/org/jruby/puma/MiniSSL.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/accept_nonblock.rb", "lib/puma/app/status.rb", "lib/puma/binder.rb", "lib/puma/capistrano.rb", "lib/puma/cli.rb", "lib/puma/client.rb", "lib/puma/cluster.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/daemon_ext.rb", "lib/puma/delegation.rb", "lib/puma/detect.rb", "lib/puma/events.rb", "lib/puma/io_buffer.rb", "lib/puma/java_io_buffer.rb", "lib/puma/jruby_restart.rb", "lib/puma/minissl.rb", "lib/puma/null_io.rb", "lib/puma/rack_default.rb", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/runner.rb", "lib/puma/server.rb", "lib/puma/single.rb", "lib/puma/thread_pool.rb", "lib/puma/util.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "tools/jungle/README.md", "tools/jungle/init.d/README.md", "tools/jungle/init.d/puma", "tools/jungle/init.d/run-puma", "tools/jungle/upstart/README.md", "tools/jungle/upstart/puma-manager.conf", "tools/jungle/upstart/puma.conf", "tools/trickletest.rb", "test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_minissl.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
|
16
16
|
s.homepage = "http://puma.io"
|
17
17
|
s.rdoc_options = ["--main", "README.md"]
|
18
18
|
s.require_paths = ["lib"]
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
def do_test(st, chunk)
|
5
|
+
s = TCPSocket.new('127.0.0.1',ARGV[0].to_i);
|
6
|
+
req = StringIO.new(st)
|
7
|
+
nout = 0
|
8
|
+
randstop = rand(st.length / 10)
|
9
|
+
STDERR.puts "stopping after: #{randstop}"
|
10
|
+
|
11
|
+
begin
|
12
|
+
while data = req.read(chunk)
|
13
|
+
nout += s.write(data)
|
14
|
+
s.flush
|
15
|
+
sleep 0.1
|
16
|
+
if nout > randstop
|
17
|
+
STDERR.puts "BANG! after #{nout} bytes."
|
18
|
+
break
|
19
|
+
end
|
20
|
+
end
|
21
|
+
rescue Object => e
|
22
|
+
STDERR.puts "ERROR: #{e}"
|
23
|
+
ensure
|
24
|
+
s.close
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
content = "-" * (1024 * 240)
|
29
|
+
st = "GET / HTTP/1.1\r\nHost: www.zedshaw.com\r\nContent-Type: text/plain\r\nContent-Length: #{content.length}\r\n\r\n#{content}"
|
30
|
+
|
31
|
+
puts "length: #{content.length}"
|
32
|
+
|
33
|
+
threads = []
|
34
|
+
ARGV[1].to_i.times do
|
35
|
+
t = Thread.new do
|
36
|
+
size = 100
|
37
|
+
puts ">>>> #{size} sized chunks"
|
38
|
+
do_test(st, size)
|
39
|
+
end
|
40
|
+
|
41
|
+
t.abort_on_exception = true
|
42
|
+
threads << t
|
43
|
+
end
|
44
|
+
|
45
|
+
threads.each {|t| t.join}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -98,6 +98,7 @@ extra_rdoc_files:
|
|
98
98
|
- README.md
|
99
99
|
- docs/config.md
|
100
100
|
- docs/nginx.md
|
101
|
+
- tools/jungle/README.md
|
101
102
|
- tools/jungle/init.d/README.md
|
102
103
|
- tools/jungle/upstart/README.md
|
103
104
|
files:
|
@@ -134,6 +135,7 @@ files:
|
|
134
135
|
- lib/puma/capistrano.rb
|
135
136
|
- lib/puma/cli.rb
|
136
137
|
- lib/puma/client.rb
|
138
|
+
- lib/puma/cluster.rb
|
137
139
|
- lib/puma/compat.rb
|
138
140
|
- lib/puma/configuration.rb
|
139
141
|
- lib/puma/const.rb
|
@@ -150,17 +152,21 @@ files:
|
|
150
152
|
- lib/puma/rack_default.rb
|
151
153
|
- lib/puma/rack_patch.rb
|
152
154
|
- lib/puma/reactor.rb
|
155
|
+
- lib/puma/runner.rb
|
153
156
|
- lib/puma/server.rb
|
157
|
+
- lib/puma/single.rb
|
154
158
|
- lib/puma/thread_pool.rb
|
155
159
|
- lib/puma/util.rb
|
156
160
|
- lib/rack/handler/puma.rb
|
157
161
|
- puma.gemspec
|
162
|
+
- tools/jungle/README.md
|
158
163
|
- tools/jungle/init.d/README.md
|
159
164
|
- tools/jungle/init.d/puma
|
160
165
|
- tools/jungle/init.d/run-puma
|
161
166
|
- tools/jungle/upstart/README.md
|
162
167
|
- tools/jungle/upstart/puma-manager.conf
|
163
168
|
- tools/jungle/upstart/puma.conf
|
169
|
+
- tools/trickletest.rb
|
164
170
|
- test/test_app_status.rb
|
165
171
|
- test/test_cli.rb
|
166
172
|
- test/test_config.rb
|