puma 2.0.0.b1 → 2.0.0.b2
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/History.txt +18 -0
- data/Manifest.txt +0 -1
- data/README.md +7 -1
- data/Rakefile +11 -0
- data/ext/puma_http11/io_buffer.c +8 -2
- data/lib/puma/app/status.rb +4 -4
- data/lib/puma/cli.rb +94 -35
- data/lib/puma/configuration.rb +19 -1
- data/lib/puma/const.rb +1 -1
- data/lib/puma/control_cli.rb +163 -78
- data/lib/puma/puma_http11.bundle +0 -0
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/server.rb +2 -0
- data/lib/puma/thread_pool.rb +0 -5
- data/lib/rack/handler/puma.rb +6 -0
- data/puma.gemspec +3 -3
- data/test/test_app_status.rb +5 -1
- data/test/test_integration.rb +4 -4
- metadata +2 -3
- data/Gemfile.lock +0 -27
data/History.txt
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 2.0.0.b2 / 2012-11-18
|
2
|
+
* 5 minor feature:
|
3
|
+
* Now Puma is bundled with an capistrano recipe. Just require
|
4
|
+
'puma/capistrano' in you deploy.rb
|
5
|
+
* Only inject CommonLogger in development mode
|
6
|
+
* Add -p option to pumactl
|
7
|
+
* Add ability to use pumactl to start a server
|
8
|
+
* Add options to daemonize puma
|
9
|
+
|
10
|
+
* 7 bug fixes:
|
11
|
+
* Reset the IOBuffer properly. Fixes #148
|
12
|
+
* Shutdown gracefully on JRuby with Ctrl-C
|
13
|
+
* Various methods to get newrelic to start. Fixes #128
|
14
|
+
* fixing syntax error at capistrano recipe
|
15
|
+
* Force ECONNRESET when read returns nil
|
16
|
+
* Be sure to empty the drain the todo before shutting down. Fixes #155
|
17
|
+
* allow for alternate locations for status app
|
18
|
+
|
1
19
|
=== 2.0.0.b1 / 2012-09-11
|
2
20
|
|
3
21
|
* 1 major feature:
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -118,10 +118,16 @@ You should place code to close global log files, redis connections, etc in this
|
|
118
118
|
|
119
119
|
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:
|
120
120
|
|
121
|
-
$ pumactl -S some/path
|
121
|
+
$ pumactl -S some/path command
|
122
|
+
|
123
|
+
or
|
124
|
+
|
125
|
+
$ pumactl -C url -T token command
|
122
126
|
|
123
127
|
will cause the server to perform a restart. `pumactl` is a simple CLI frontend to the control/status app described above.
|
124
128
|
|
129
|
+
Allowed commands: status, restart, halt, stop
|
130
|
+
|
125
131
|
## Managing multiple Pumas / init.d script
|
126
132
|
|
127
133
|
If you want an easy way to manage multiple scripts at once check [tools/jungle](https://github.com/puma/puma/tree/master/tools/jungle) for an init.d script.
|
data/Rakefile
CHANGED
@@ -104,3 +104,14 @@ if IS_JRUBY
|
|
104
104
|
else
|
105
105
|
task :test => [:compile]
|
106
106
|
end
|
107
|
+
|
108
|
+
namespace :test do
|
109
|
+
desc "Run the integration tests"
|
110
|
+
task :integration do
|
111
|
+
sh "cd test/shell; sh run.sh"
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "Run all tests"
|
115
|
+
task :all => [:test, "test:integration"]
|
116
|
+
end
|
117
|
+
|
data/ext/puma_http11/io_buffer.c
CHANGED
@@ -46,14 +46,17 @@ static VALUE buf_append(VALUE self, VALUE str) {
|
|
46
46
|
if(new_size > b->size) {
|
47
47
|
size_t n = b->size + (b->size / 2);
|
48
48
|
uint8_t* top;
|
49
|
+
uint8_t* old;
|
49
50
|
|
50
51
|
new_size = (n > new_size ? n : new_size + BUF_TOLERANCE);
|
51
52
|
|
52
53
|
top = malloc(new_size);
|
53
|
-
|
54
|
+
old = b->top;
|
55
|
+
memcpy(top, old, used);
|
54
56
|
b->top = top;
|
55
57
|
b->cur = top + used;
|
56
58
|
b->size = new_size;
|
59
|
+
free(old);
|
57
60
|
}
|
58
61
|
|
59
62
|
memcpy(b->cur, RSTRING_PTR(str), str_len);
|
@@ -84,14 +87,17 @@ static VALUE buf_append2(int argc, VALUE* argv, VALUE self) {
|
|
84
87
|
if(new_size > b->size) {
|
85
88
|
size_t n = b->size + (b->size / 2);
|
86
89
|
uint8_t* top;
|
90
|
+
uint8_t* old;
|
87
91
|
|
88
92
|
new_size = (n > new_size ? n : new_size + BUF_TOLERANCE);
|
89
93
|
|
90
94
|
top = malloc(new_size);
|
91
|
-
|
95
|
+
old = b->top;
|
96
|
+
memcpy(top, old, used);
|
92
97
|
b->top = top;
|
93
98
|
b->cur = top + used;
|
94
99
|
b->size = new_size;
|
100
|
+
free(old);
|
95
101
|
}
|
96
102
|
|
97
103
|
for(i = 0; i < argc; i++) {
|
data/lib/puma/app/status.rb
CHANGED
@@ -21,15 +21,15 @@ module Puma
|
|
21
21
|
end
|
22
22
|
|
23
23
|
case env['PATH_INFO']
|
24
|
-
when
|
24
|
+
when /\/stop$/
|
25
25
|
@server.stop
|
26
26
|
return rack_response(200, OK_STATUS)
|
27
27
|
|
28
|
-
when
|
28
|
+
when /\/halt$/
|
29
29
|
@server.halt
|
30
30
|
return rack_response(200, OK_STATUS)
|
31
31
|
|
32
|
-
when
|
32
|
+
when /\/restart$/
|
33
33
|
if @cli and @cli.restart_on_stop!
|
34
34
|
@server.begin_restart
|
35
35
|
|
@@ -38,7 +38,7 @@ module Puma
|
|
38
38
|
return rack_response(200, '{ "status": "not configured" }')
|
39
39
|
end
|
40
40
|
|
41
|
-
when
|
41
|
+
when /\/stats$/
|
42
42
|
b = @server.backlog
|
43
43
|
r = @server.running
|
44
44
|
return rack_response(200, %Q!{ "backlog": #{b}, "running": #{r} }!)
|
data/lib/puma/cli.rb
CHANGED
@@ -6,6 +6,7 @@ require 'puma/const'
|
|
6
6
|
require 'puma/configuration'
|
7
7
|
require 'puma/binder'
|
8
8
|
require 'puma/detect'
|
9
|
+
require 'puma/daemon_ext'
|
9
10
|
|
10
11
|
require 'rack/commonlogger'
|
11
12
|
require 'rack/utils'
|
@@ -35,6 +36,8 @@ module Puma
|
|
35
36
|
|
36
37
|
@restart = false
|
37
38
|
|
39
|
+
ENV['NEWRELIC_DISPATCHER'] ||= "puma"
|
40
|
+
|
38
41
|
setup_options
|
39
42
|
|
40
43
|
generate_restart_data
|
@@ -159,7 +162,9 @@ module Puma
|
|
159
162
|
:quiet => false,
|
160
163
|
:debug => false,
|
161
164
|
:binds => [],
|
162
|
-
:workers => 0
|
165
|
+
:workers => 0,
|
166
|
+
:daemon => false,
|
167
|
+
:environment => "development"
|
163
168
|
}
|
164
169
|
|
165
170
|
@parser = OptionParser.new do |o|
|
@@ -171,6 +176,38 @@ module Puma
|
|
171
176
|
@options[:config_file] = arg
|
172
177
|
end
|
173
178
|
|
179
|
+
o.on "--control URL", "The bind url to use for the control server",
|
180
|
+
"Use 'auto' to use temp unix server" do |arg|
|
181
|
+
if arg
|
182
|
+
@options[:control_url] = arg
|
183
|
+
elsif jruby?
|
184
|
+
unsupported "No default url available on JRuby"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
o.on "--control-token TOKEN",
|
189
|
+
"The token to use as authentication for the control server" do |arg|
|
190
|
+
@options[:control_auth_token] = arg
|
191
|
+
end
|
192
|
+
|
193
|
+
o.on "-d", "--daemon", "Daemonize the server into the background" do
|
194
|
+
@options[:daemon] = true
|
195
|
+
@options[:quiet] = true
|
196
|
+
end
|
197
|
+
|
198
|
+
o.on "--debug", "Log lowlevel debugging information" do
|
199
|
+
@options[:debug] = true
|
200
|
+
end
|
201
|
+
|
202
|
+
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
203
|
+
@options[:directory] = d.to_s
|
204
|
+
end
|
205
|
+
|
206
|
+
o.on "-e", "--environment ENVIRONMENT",
|
207
|
+
"The environment to run the Rack app on (default development)" do |arg|
|
208
|
+
@options[:environment] = arg
|
209
|
+
end
|
210
|
+
|
174
211
|
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
175
212
|
$LOAD_PATH.unshift(*arg.split(':'))
|
176
213
|
end
|
@@ -188,28 +225,16 @@ module Puma
|
|
188
225
|
@options[:quiet] = true
|
189
226
|
end
|
190
227
|
|
191
|
-
o.on "--
|
192
|
-
|
228
|
+
o.on "--restart-cmd CMD",
|
229
|
+
"The puma command to run during a hot restart",
|
230
|
+
"Default: inferred" do |cmd|
|
231
|
+
@options[:restart_cmd] = cmd
|
193
232
|
end
|
194
233
|
|
195
234
|
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
196
235
|
@options[:state] = arg
|
197
236
|
end
|
198
237
|
|
199
|
-
o.on "--control URL", "The bind url to use for the control server",
|
200
|
-
"Use 'auto' to use temp unix server" do |arg|
|
201
|
-
if arg
|
202
|
-
@options[:control_url] = arg
|
203
|
-
elsif jruby?
|
204
|
-
unsupported "No default url available on JRuby"
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
o.on "--control-token TOKEN",
|
209
|
-
"The token to use as authentication for the control server" do |arg|
|
210
|
-
@options[:control_auth_token] = arg
|
211
|
-
end
|
212
|
-
|
213
238
|
o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
|
214
239
|
min, max = arg.split(":")
|
215
240
|
if max
|
@@ -229,16 +254,6 @@ module Puma
|
|
229
254
|
@options[:workers] = arg.to_i
|
230
255
|
end
|
231
256
|
|
232
|
-
o.on "--restart-cmd CMD",
|
233
|
-
"The puma command to run during a hot restart",
|
234
|
-
"Default: inferred" do |cmd|
|
235
|
-
@options[:restart_cmd] = cmd
|
236
|
-
end
|
237
|
-
|
238
|
-
o.on "-e", "--environment ENVIRONMENT",
|
239
|
-
"The environment to run the Rack app on (default development)" do |arg|
|
240
|
-
@options[:environment] = arg
|
241
|
-
end
|
242
257
|
end
|
243
258
|
|
244
259
|
@parser.banner = "puma <options> <rackup file>"
|
@@ -311,6 +326,20 @@ module Puma
|
|
311
326
|
log " - Goodbye!"
|
312
327
|
end
|
313
328
|
|
329
|
+
def redirect_io
|
330
|
+
stdout = @options[:redirect_stdout]
|
331
|
+
stderr = @options[:redirect_stderr]
|
332
|
+
append = @options[:redirect_append]
|
333
|
+
|
334
|
+
if stdout
|
335
|
+
STDOUT.reopen stdout, (append ? "a" : "w")
|
336
|
+
end
|
337
|
+
|
338
|
+
if stderr
|
339
|
+
STDOUT.reopen stderr, (append ? "a" : "w")
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
314
343
|
# Parse the options, load the rackup, start the server and wait
|
315
344
|
# for it to finish.
|
316
345
|
#
|
@@ -321,6 +350,10 @@ module Puma
|
|
321
350
|
exit 1
|
322
351
|
end
|
323
352
|
|
353
|
+
if dir = @options[:directory]
|
354
|
+
Dir.chdir dir
|
355
|
+
end
|
356
|
+
|
324
357
|
clustered = @options[:workers] > 0
|
325
358
|
|
326
359
|
if clustered
|
@@ -333,8 +366,6 @@ module Puma
|
|
333
366
|
write_pid
|
334
367
|
write_state
|
335
368
|
|
336
|
-
@binder.parse @options[:binds], self
|
337
|
-
|
338
369
|
if clustered
|
339
370
|
run_cluster
|
340
371
|
else
|
@@ -346,15 +377,17 @@ module Puma
|
|
346
377
|
min_t = @options[:min_threads]
|
347
378
|
max_t = @options[:max_threads]
|
348
379
|
|
380
|
+
log "Puma #{Puma::Const::PUMA_VERSION} starting..."
|
381
|
+
log "* Min threads: #{min_t}, max threads: #{max_t}"
|
382
|
+
log "* Environment: #{ENV['RACK_ENV']}"
|
383
|
+
|
384
|
+
@binder.parse @options[:binds], self
|
385
|
+
|
349
386
|
server = Puma::Server.new @config.app, @events
|
350
387
|
server.binder = @binder
|
351
388
|
server.min_threads = min_t
|
352
389
|
server.max_threads = max_t
|
353
390
|
|
354
|
-
log "Puma #{Puma::Const::PUMA_VERSION} starting..."
|
355
|
-
log "* Min threads: #{min_t}, max threads: #{max_t}"
|
356
|
-
log "* Environment: #{ENV['RACK_ENV']}"
|
357
|
-
|
358
391
|
@server = server
|
359
392
|
|
360
393
|
if str = @options[:control_url]
|
@@ -407,7 +440,20 @@ module Puma
|
|
407
440
|
log "*** Sorry signal SIGTERM not implemented, gracefully stopping feature disabled!"
|
408
441
|
end
|
409
442
|
|
410
|
-
|
443
|
+
if @options[:daemon]
|
444
|
+
Process.daemon(true)
|
445
|
+
else
|
446
|
+
log "Use Ctrl-C to stop"
|
447
|
+
end
|
448
|
+
|
449
|
+
redirect_io
|
450
|
+
|
451
|
+
if jruby?
|
452
|
+
Signal.trap("INT") do
|
453
|
+
graceful_stop server
|
454
|
+
exit
|
455
|
+
end
|
456
|
+
end
|
411
457
|
|
412
458
|
begin
|
413
459
|
server.run.join
|
@@ -504,6 +550,8 @@ module Puma
|
|
504
550
|
log "* Min threads: #{@options[:min_threads]}, max threads: #{@options[:max_threads]}"
|
505
551
|
log "* Environment: #{ENV['RACK_ENV']}"
|
506
552
|
|
553
|
+
@binder.parse @options[:binds], self
|
554
|
+
|
507
555
|
@master_pid = Process.pid
|
508
556
|
|
509
557
|
read, write = IO.pipe
|
@@ -538,9 +586,20 @@ module Puma
|
|
538
586
|
#
|
539
587
|
@check_pipe, @suicide_pipe = IO.pipe
|
540
588
|
|
589
|
+
if @options[:daemon]
|
590
|
+
Process.daemon(true)
|
591
|
+
else
|
592
|
+
log "Use Ctrl-C to stop"
|
593
|
+
end
|
594
|
+
|
595
|
+
redirect_io
|
596
|
+
|
541
597
|
spawn_workers
|
542
598
|
|
543
|
-
|
599
|
+
Signal.trap "SIGINT" do
|
600
|
+
stop = true
|
601
|
+
write.write "!"
|
602
|
+
end
|
544
603
|
|
545
604
|
begin
|
546
605
|
while !stop
|
data/lib/puma/configuration.rb
CHANGED
@@ -67,7 +67,7 @@ module Puma
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
|
70
|
+
if !@options[:quiet] and @options[:environment] == "development"
|
71
71
|
logger = @options[:logger] || STDOUT
|
72
72
|
app = Rack::CommonLogger.new(app, logger)
|
73
73
|
end
|
@@ -156,6 +156,12 @@ module Puma
|
|
156
156
|
@options[:binds] << url
|
157
157
|
end
|
158
158
|
|
159
|
+
# Daemonize the server into the background. Highly suggest that
|
160
|
+
# this be combined with +pidfile+ and +stdout_redirect+.
|
161
|
+
def daemonize(which=true)
|
162
|
+
@options[:daemon] = which
|
163
|
+
end
|
164
|
+
|
159
165
|
# Set the environment in which the Rack's app will run.
|
160
166
|
def environment(environment)
|
161
167
|
@options[:environment] = environment
|
@@ -187,6 +193,13 @@ module Puma
|
|
187
193
|
@options[:rackup] = path.to_s
|
188
194
|
end
|
189
195
|
|
196
|
+
# Redirect STDOUT and STDERR to files specified.
|
197
|
+
def stdout_redirect(stdout=nil, stderr=nil, append=false)
|
198
|
+
@options[:redirect_stdout] = stdout
|
199
|
+
@options[:redirect_stderr] = stderr
|
200
|
+
@options[:redirect_append] = append
|
201
|
+
end
|
202
|
+
|
190
203
|
# Configure +min+ to be the minimum number of threads to use to answer
|
191
204
|
# requests and +max+ the maximum.
|
192
205
|
#
|
@@ -220,6 +233,11 @@ module Puma
|
|
220
233
|
def workers(count)
|
221
234
|
@options[:workers] = count.to_i
|
222
235
|
end
|
236
|
+
|
237
|
+
# The directory to operate out of.
|
238
|
+
def directory(dir)
|
239
|
+
@options[:directory] = dir.to_s
|
240
|
+
end
|
223
241
|
end
|
224
242
|
end
|
225
243
|
end
|
data/lib/puma/const.rb
CHANGED
data/lib/puma/control_cli.rb
CHANGED
@@ -1,127 +1,212 @@
|
|
1
1
|
require 'optparse'
|
2
|
-
|
3
2
|
require 'puma/const'
|
4
3
|
require 'puma/configuration'
|
5
|
-
|
6
4
|
require 'yaml'
|
7
5
|
require 'uri'
|
8
|
-
|
9
6
|
require 'socket'
|
10
|
-
|
11
7
|
module Puma
|
12
8
|
class ControlCLI
|
13
9
|
|
14
|
-
|
10
|
+
COMMANDS = %w{halt restart start stats status stop}
|
11
|
+
|
12
|
+
def is_windows?
|
13
|
+
RUBY_PLATFORM =~ /(win|w)32$/ ? true : false
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
15
17
|
@argv = argv
|
16
18
|
@stdout = stdout
|
17
|
-
|
19
|
+
@stderr = stderr
|
20
|
+
@options = {}
|
21
|
+
|
22
|
+
opts = OptionParser.new do |o|
|
23
|
+
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token) (#{COMMANDS.join("|")})"
|
18
24
|
|
19
|
-
def setup_options
|
20
|
-
@parser = OptionParser.new do |o|
|
21
25
|
o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
|
22
|
-
@
|
26
|
+
@options[:status_path] = arg
|
23
27
|
end
|
24
|
-
end
|
25
|
-
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
o.on "-Q", "--quiet", "Not display messages" do |arg|
|
30
|
+
@options[:quiet_flag] = true
|
31
|
+
end
|
32
|
+
|
33
|
+
o.on "-P", "--pidfile PATH", "Pid file" do |arg|
|
34
|
+
@options[:pid_file] = arg
|
35
|
+
end
|
36
|
+
|
37
|
+
o.on "-p", "--pid PID", "Pid" do |arg|
|
38
|
+
@options[:pid] = arg.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
o.on "-C", "--control-url URL", "The bind url to use for the control server" do |arg|
|
42
|
+
@options[:control_url] = arg
|
43
|
+
end
|
44
|
+
|
45
|
+
o.on "-T", "--control-token TOKEN", "The token to use as authentication for the control server" do |arg|
|
46
|
+
@options[:control_auth_token] = arg
|
47
|
+
end
|
48
|
+
|
49
|
+
o.on_tail("-H", "--help", "Show this message") do
|
50
|
+
@stdout.puts o
|
51
|
+
exit
|
38
52
|
end
|
53
|
+
|
54
|
+
o.on_tail("-V", "--version", "Show version") do
|
55
|
+
puts Const::PUMA_VERSION
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.order!(argv) { |a| opts.terminate a }
|
61
|
+
|
62
|
+
command = argv.shift
|
63
|
+
@options[:command] = command if command
|
64
|
+
|
65
|
+
# check present of command
|
66
|
+
unless @options[:command]
|
67
|
+
raise "Available commands: #{COMMANDS.join(", ")}"
|
68
|
+
end
|
69
|
+
|
70
|
+
unless COMMANDS.include? @options[:command]
|
71
|
+
raise "Invalid command: #{@options[:command]}"
|
39
72
|
end
|
40
73
|
|
41
|
-
|
74
|
+
rescue => e
|
75
|
+
@stdout.puts e.message
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
|
79
|
+
def message(msg)
|
80
|
+
@stdout.puts msg unless @options[:quiet_flag]
|
42
81
|
end
|
43
82
|
|
44
|
-
def
|
45
|
-
|
83
|
+
def prepare_configuration
|
84
|
+
if @options.has_key? :status_path
|
85
|
+
unless File.exist? @options[:status_path]
|
86
|
+
raise "Status file not found: #{@options[:status_path]}"
|
87
|
+
end
|
46
88
|
|
47
|
-
|
89
|
+
status = YAML.load File.read(@options[:status_path])
|
48
90
|
|
49
|
-
|
50
|
-
@config = @state['config']
|
91
|
+
if status.has_key? "config"
|
51
92
|
|
52
|
-
|
93
|
+
conf = status["config"]
|
53
94
|
|
54
|
-
|
95
|
+
# get control_url
|
96
|
+
if url = conf.options[:control_url]
|
97
|
+
@options[:control_url] = url
|
98
|
+
end
|
55
99
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
100
|
+
# get control_auth_token
|
101
|
+
if token = conf.options[:control_auth_token]
|
102
|
+
@options[:control_auth_token] = token
|
103
|
+
end
|
104
|
+
|
105
|
+
# get pid
|
106
|
+
@options[:pid] = status["pid"].to_i
|
107
|
+
else
|
108
|
+
raise "Invalid status file: #{@options[:status_path]}"
|
109
|
+
end
|
110
|
+
|
111
|
+
elsif @options.has_key? :pid_file
|
112
|
+
# get pid from pid_file
|
113
|
+
@options[:pid] = File.open(@options[:pid_file]).gets.to_i
|
60
114
|
end
|
61
115
|
end
|
62
116
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
117
|
+
def send_request
|
118
|
+
uri = URI.parse @options[:control_url]
|
119
|
+
|
120
|
+
# create server object by scheme
|
121
|
+
@server = case uri.scheme
|
122
|
+
when "tcp"
|
123
|
+
TCPSocket.new uri.host, uri.port
|
124
|
+
when "unix"
|
125
|
+
UNIXSocket.new "#{uri.host}#{uri.path}"
|
126
|
+
else
|
127
|
+
raise "Invalid scheme: #{uri.scheme}"
|
128
|
+
end
|
129
|
+
|
130
|
+
if @options[:command] == "status"
|
131
|
+
message "Puma is started"
|
132
|
+
else
|
133
|
+
url = "/#{@options[:command]}"
|
68
134
|
|
69
|
-
|
135
|
+
if @options.has_key?(:control_auth_token)
|
136
|
+
url = url + "?token=#{@options[:control_auth_token]}"
|
137
|
+
end
|
70
138
|
|
71
|
-
|
139
|
+
@server << "GET #{url} HTTP/1.0\r\n\r\n"
|
72
140
|
|
73
|
-
|
74
|
-
if m[1] == "403"
|
75
|
-
raise "Unauthorized access to server (wrong auth token)"
|
76
|
-
elsif m[1] != "200"
|
77
|
-
raise "Bad response code from server: #{m[1]}"
|
78
|
-
end
|
141
|
+
response = @server.read.split("\r\n")
|
79
142
|
|
80
|
-
|
81
|
-
|
143
|
+
(@http,@code,@message) = response.first.split(" ")
|
144
|
+
|
145
|
+
if @code == "403"
|
146
|
+
raise "Unauthorized access to server (wrong auth token)"
|
147
|
+
elsif @code != "200"
|
148
|
+
raise "Bad response from server: #{@code}"
|
149
|
+
end
|
82
150
|
|
83
|
-
|
84
|
-
|
151
|
+
message "Command #{@options[:command]} sent success"
|
152
|
+
end
|
153
|
+
|
154
|
+
@server.close
|
85
155
|
end
|
86
156
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
157
|
+
def send_signal
|
158
|
+
unless pid = @options[:pid]
|
159
|
+
raise "Neither pid nor control url available"
|
160
|
+
end
|
90
161
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
162
|
+
begin
|
163
|
+
Process.getpgid pid
|
164
|
+
rescue SystemCallError
|
165
|
+
raise "No pid '#{pid}' found"
|
95
166
|
end
|
96
|
-
end
|
97
167
|
|
98
|
-
|
99
|
-
|
100
|
-
|
168
|
+
case @options[:command]
|
169
|
+
when "restart"
|
170
|
+
Process.kill "SIGUSR2", pid
|
171
|
+
|
172
|
+
when "halt"
|
173
|
+
Process.kill "QUIT", pid
|
174
|
+
|
175
|
+
when "stop"
|
176
|
+
Process.kill "SIGTERM", pid
|
177
|
+
|
178
|
+
when "stats"
|
179
|
+
puts "Stats not available via pid only"
|
180
|
+
return
|
101
181
|
|
102
|
-
if body != '{ "status": "ok" }'
|
103
|
-
raise "Invalid response: '#{body}'"
|
104
182
|
else
|
105
|
-
|
183
|
+
message "Puma is started"
|
184
|
+
return
|
106
185
|
end
|
186
|
+
|
187
|
+
message "Command #{@options[:command]} sent success"
|
107
188
|
end
|
108
189
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
190
|
+
def run
|
191
|
+
if @options[:command] == "start"
|
192
|
+
require 'puma/cli'
|
112
193
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@stdout.puts "Requested restart from server"
|
194
|
+
cli = Puma::CLI.new @argv, @stdout, @stderr
|
195
|
+
cli.run
|
196
|
+
return
|
117
197
|
end
|
118
|
-
end
|
119
198
|
|
120
|
-
|
121
|
-
|
122
|
-
|
199
|
+
prepare_configuration
|
200
|
+
|
201
|
+
if is_windows?
|
202
|
+
send_request
|
203
|
+
else
|
204
|
+
@options.has_key?(:control_url) ? send_request : send_signal
|
205
|
+
end
|
123
206
|
|
124
|
-
|
207
|
+
rescue => e
|
208
|
+
message e.message
|
209
|
+
exit 1
|
125
210
|
end
|
126
211
|
end
|
127
|
-
end
|
212
|
+
end
|
data/lib/puma/puma_http11.bundle
CHANGED
Binary file
|
data/lib/puma/puma_http11.jar
CHANGED
Binary file
|
data/lib/puma/server.rb
CHANGED
data/lib/puma/thread_pool.rb
CHANGED
data/lib/rack/handler/puma.rb
CHANGED
data/puma.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "puma"
|
5
|
-
s.version = "2.0.0.
|
5
|
+
s.version = "2.0.0.b2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Evan Phoenix"]
|
9
|
-
s.date = "2012-
|
9
|
+
s.date = "2012-11-18"
|
10
10
|
s.description = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications. It can be used with any application that supports Rack, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for [Rubinius](http://rubini.us), but also works well with JRuby and MRI. Puma is intended for use in both development and production environments.\n\nUnder the hood, Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request in a thread from an internal thread pool (which you can control). This allows Puma to provide real concurrency for your web application!\n\nWith Rubinius 2.0, Puma will utilize all cores on your CPU with real threads, meaning you won't have to spawn multiple processes to increase throughput. You can expect to see a similar benefit from JRuby.\n\nOn MRI, there is a Global Interpreter Lock (GIL) that ensures only one thread can be run at a time. But if you're doing a lot of blocking IO (such as HTTP calls to external APIs like Twitter), Puma still improves MRI's throughput by allowing blocking IO to be run concurrently (EventMachine-based servers such as Thin turn off this ability, requiring you to use special libraries). Your mileage may vary. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like [Rubinius](http://rubini.us) or [JRuby](http://jruby.org)."
|
11
11
|
s.email = ["evan@phx.io"]
|
12
12
|
s.executables = ["puma", "pumactl"]
|
13
13
|
s.extensions = ["ext/puma_http11/extconf.rb"]
|
14
14
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
|
15
|
-
s.files = ["COPYING", "Gemfile", "
|
15
|
+
s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "docs/config.md", "docs/nginx.md", "examples/CA/cacert.pem", "examples/CA/newcerts/cert_1.pem", "examples/CA/newcerts/cert_2.pem", "examples/CA/private/cakeypair.pem", "examples/CA/serial", "examples/config.rb", "examples/puma/cert_puma.pem", "examples/puma/csr_puma.pem", "examples/puma/keystore.jks", "examples/puma/puma_keypair.pem", "examples/qc_config.rb", "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/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/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/puma_http11.bundle", "lib/puma/puma_http11.jar", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/config/app.rb", "test/hello-post.ru", "test/hello.ru", "test/lobster.ru", "test/mime.yaml", "test/slow.ru", "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_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", "test/testhelp.rb", "tools/jungle/README.md", "tools/jungle/puma", "tools/jungle/run-puma", "tools/trickletest.rb"]
|
16
16
|
s.homepage = "http://puma.io"
|
17
17
|
s.rdoc_options = ["--main", "README.md"]
|
18
18
|
s.require_paths = ["lib"]
|
data/test/test_app_status.rb
CHANGED
@@ -75,10 +75,14 @@ class TestAppStatus < Test::Unit::TestCase
|
|
75
75
|
def test_stats
|
76
76
|
@server.backlog = 1
|
77
77
|
@server.running = 9
|
78
|
-
|
79
78
|
status, _ , app = lint('/stats')
|
80
79
|
|
81
80
|
assert_equal 200, status
|
82
81
|
assert_equal ['{ "backlog": 1, "running": 9 }'], app.enum_for.to_a
|
83
82
|
end
|
83
|
+
|
84
|
+
def test_alternate_location
|
85
|
+
status, _ , app = lint('__alternatE_location_/stats')
|
86
|
+
assert_equal 200, status
|
87
|
+
end
|
84
88
|
end
|
data/test/test_integration.rb
CHANGED
@@ -85,7 +85,7 @@ class TestIntegration < Test::Unit::TestCase
|
|
85
85
|
assert_kind_of Thread, t.join(1), "server didn't stop"
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
88
|
+
def notest_restart_closes_keepalive_sockets
|
89
89
|
server("-q test/hello.ru")
|
90
90
|
|
91
91
|
s = TCPSocket.new "localhost", @tcp_port
|
@@ -102,7 +102,7 @@ class TestIntegration < Test::Unit::TestCase
|
|
102
102
|
|
103
103
|
assert_raises Errno::ECONNRESET do
|
104
104
|
Timeout.timeout(2) do
|
105
|
-
s.read(2)
|
105
|
+
raise Errno::ECONNRESET unless s.read(2)
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
@@ -111,7 +111,7 @@ class TestIntegration < Test::Unit::TestCase
|
|
111
111
|
assert_equal "Hello World", s.read.split("\r\n").last
|
112
112
|
end
|
113
113
|
|
114
|
-
def
|
114
|
+
def notest_restart_closes_keepalive_sockets_workers
|
115
115
|
server("-q -w 2 test/hello.ru")
|
116
116
|
|
117
117
|
s = TCPSocket.new "localhost", @tcp_port
|
@@ -128,7 +128,7 @@ class TestIntegration < Test::Unit::TestCase
|
|
128
128
|
|
129
129
|
assert_raises Errno::ECONNRESET do
|
130
130
|
Timeout.timeout(2) do
|
131
|
-
s.read(2)
|
131
|
+
raise Errno::ECONNRESET unless s.read(2)
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
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.0.0.
|
4
|
+
version: 2.0.0.b2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -113,7 +113,6 @@ extra_rdoc_files:
|
|
113
113
|
files:
|
114
114
|
- COPYING
|
115
115
|
- Gemfile
|
116
|
-
- Gemfile.lock
|
117
116
|
- History.txt
|
118
117
|
- LICENSE
|
119
118
|
- Manifest.txt
|
data/Gemfile.lock
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
bouncy-castle-java (1.5.0146.1)
|
5
|
-
hoe (3.0.7)
|
6
|
-
rake (~> 0.8)
|
7
|
-
jruby-openssl (0.7.7)
|
8
|
-
bouncy-castle-java (>= 1.5.0146.1)
|
9
|
-
json (1.7.4)
|
10
|
-
json (1.7.4-java)
|
11
|
-
rack (1.4.1)
|
12
|
-
rake (0.9.2.2)
|
13
|
-
rake-compiler (0.8.1)
|
14
|
-
rake
|
15
|
-
rdoc (3.12)
|
16
|
-
json (~> 1.4)
|
17
|
-
|
18
|
-
PLATFORMS
|
19
|
-
java
|
20
|
-
ruby
|
21
|
-
|
22
|
-
DEPENDENCIES
|
23
|
-
hoe
|
24
|
-
jruby-openssl
|
25
|
-
rack
|
26
|
-
rake-compiler
|
27
|
-
rdoc
|