puma 2.6.0-java → 2.7.0-java
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 +17 -0
- data/README.md +15 -15
- data/ext/puma_http11/org/jruby/puma/Http11.java +2 -2
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma/capistrano.rb +6 -1
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/cluster.rb +11 -0
- data/lib/puma/compat.rb +8 -1
- data/lib/puma/const.rb +2 -2
- data/lib/puma/daemon_ext.rb +5 -1
- data/lib/puma/minissl.rb +10 -2
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/reactor.rb +32 -12
- data/lib/puma/server.rb +1 -1
- data/test/test_http11.rb +21 -2
- data/tools/jungle/upstart/puma.conf +3 -4
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
=== 2.7.0 / 2013-12-03
|
2
|
+
|
3
|
+
* 1 minor feature:
|
4
|
+
* Adding TTIN and TTOU to increment/decrement workers
|
5
|
+
|
6
|
+
* N bug fixes:
|
7
|
+
* Always use our Process.daemon because it's not busted
|
8
|
+
* Add capistrano restart failback to start.
|
9
|
+
* Change position of `cd` so that rvm gemset is loaded
|
10
|
+
* Clarify some platform specifics
|
11
|
+
* Do not close the pipe sockets when retrying
|
12
|
+
* Fix String#byteslice for Ruby 1.9.1, 1.9.2
|
13
|
+
* Fix compatibility with 1.8.7.
|
14
|
+
* Handle IOError closed stream in IO.select
|
15
|
+
* Increase the max URI path length to 2048 chars from 1024 chars
|
16
|
+
* Upstart jungle use config/puma.rb instead
|
17
|
+
|
1
18
|
=== 2.6.0 / 2013-09-13
|
2
19
|
|
3
20
|
* 2 minor features:
|
data/README.md
CHANGED
@@ -22,7 +22,7 @@ The easiest way to get started with Puma is to install it via RubyGems. You can
|
|
22
22
|
|
23
23
|
$ gem install puma
|
24
24
|
|
25
|
-
Now you should have the puma command available in your PATH, so just do the following in the root folder of your Rack application:
|
25
|
+
Now you should have the `puma` command available in your PATH, so just do the following in the root folder of your Rack application:
|
26
26
|
|
27
27
|
$ puma app.ru
|
28
28
|
|
@@ -82,7 +82,7 @@ Puma 2 offers clustered mode, allowing you to use forked processes to handle mul
|
|
82
82
|
On a ruby implementation that offers native threads, you should tune this number to match the number of cores available.
|
83
83
|
Note that threads are still used in clustered mode, and the `-t` thread flag setting is per worker, so `-w 2 -t 16:16` will be 32 threads.
|
84
84
|
|
85
|
-
If you're running in Clustered Mode you can optionally choose to preload your application before starting up the workers. To do this simply specify the `--preload` flag in invocation:
|
85
|
+
If you're running in Clustered Mode you can optionally choose to preload your application before starting up the workers. This is necessary in order to take advantate of the [Copy on Write](http://en.wikipedia.org/wiki/Copy-on-write) feature introduced in [MRI Ruby 2.0](https://blog.heroku.com/archives/2013/3/6/matz_highlights_ruby_2_0_at_waza). To do this simply specify the `--preload` flag in invocation:
|
86
86
|
|
87
87
|
# CLI invocation
|
88
88
|
$ puma -t 8:32 -w 3 --preload
|
@@ -104,7 +104,7 @@ Additionally, you can specify a block in your configuration file that will be ru
|
|
104
104
|
end
|
105
105
|
|
106
106
|
This code can be used to setup the process before booting the application, allowing
|
107
|
-
you to do some
|
107
|
+
you to do some Puma-specific things that you don't want to embed in your application.
|
108
108
|
For instance, you could fire a log notification that a worker booted or send something to statsd.
|
109
109
|
This can be called multiple times to add hooks.
|
110
110
|
|
@@ -137,15 +137,15 @@ Need a bit of security? Use SSL sockets!
|
|
137
137
|
|
138
138
|
### Control/Status Server
|
139
139
|
|
140
|
-
Puma comes with a builtin status/control app that can be used query and control
|
140
|
+
Puma comes with a builtin status/control app that can be used query and control Puma itself. Here is an example of starting Puma with the control server:
|
141
141
|
|
142
142
|
$ puma --control tcp://127.0.0.1:9293 --control-token foo
|
143
143
|
|
144
|
-
This directs
|
144
|
+
This directs Puma to start the control server on localhost port 9293. Additionally, all requests to the control server will need to include `token=foo` as a query parameter. This allows for simple authentication. Check out [status.rb](https://github.com/puma/puma/blob/master/lib/puma/app/status.rb) to see what the app has available.
|
145
145
|
|
146
146
|
### Configuration file
|
147
147
|
|
148
|
-
You can also provide a configuration file which
|
148
|
+
You can also provide a configuration file which Puma will use with the `-C` (or `--config`) flag:
|
149
149
|
|
150
150
|
$ puma -C /path/to/config
|
151
151
|
|
@@ -153,30 +153,30 @@ Take the following [sample configuration](https://github.com/puma/puma/blob/mast
|
|
153
153
|
|
154
154
|
## Restart
|
155
155
|
|
156
|
-
Puma includes the ability to restart itself allowing easy upgrades to new versions. When available (MRI, Rubinius, JRuby),
|
156
|
+
Puma includes the ability to restart itself allowing easy upgrades to new versions. When available (MRI, Rubinius, JRuby), Puma performs a "hot restart". This is the same functionality available in *unicorn* and *nginx* which keep the server sockets open between restarts. This makes sure that no pending requests are dropped while the restart is taking place.
|
157
157
|
|
158
158
|
To perform a restart, there are 2 builtin mechanisms:
|
159
159
|
|
160
|
-
* Send the puma process the `SIGUSR2` signal
|
160
|
+
* Send the `puma` process the `SIGUSR2` signal
|
161
161
|
* Use the status server and issue `/restart`
|
162
162
|
|
163
|
-
No code is shared between the current and restarted process, so it should be safe to issue a restart any place where you would manually stop
|
163
|
+
No code is shared between the current and restarted process, so it should be safe to issue a restart any place where you would manually stop Puma and start it again.
|
164
164
|
|
165
|
-
If the new process is unable to load, it will simply exit. You should therefore run
|
165
|
+
If the new process is unable to load, it will simply exit. You should therefore run Puma under a supervisor when using it in production.
|
166
166
|
|
167
167
|
### Cleanup Code
|
168
168
|
|
169
|
-
Puma isn't able to understand all the resources that your app may use, so it provides a hook in the configuration file you pass to `-C` called `on_restart`. The block passed to `on_restart` will be called, unsurprisingly, just before
|
169
|
+
Puma isn't able to understand all the resources that your app may use, so it provides a hook in the configuration file you pass to `-C` called `on_restart`. The block passed to `on_restart` will be called, unsurprisingly, just before Puma restarts itself.
|
170
170
|
|
171
171
|
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.
|
172
172
|
|
173
173
|
### Platform Constraints
|
174
174
|
|
175
|
-
Because of various platforms not being implement certain things, the following differences occur when
|
175
|
+
Because of various platforms not being implement certain things, the following differences occur when Puma is used on different platforms:
|
176
176
|
|
177
|
-
*
|
178
|
-
*
|
179
|
-
*
|
177
|
+
* **JRuby**, **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
|
178
|
+
* **JRuby**, **Windows**: cluster mode is not supported due to a lack of fork(2)
|
179
|
+
* **Windows**: daemon mode is not supported due to a lack of fork(2)
|
180
180
|
|
181
181
|
## pumactl
|
182
182
|
|
@@ -30,8 +30,8 @@ public class Http11 extends RubyObject {
|
|
30
30
|
public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the 12288 allowed length.";
|
31
31
|
public final static int MAX_FRAGMENT_LENGTH = 1024;
|
32
32
|
public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 1024 allowed length.";
|
33
|
-
public final static int MAX_REQUEST_PATH_LENGTH =
|
34
|
-
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the
|
33
|
+
public final static int MAX_REQUEST_PATH_LENGTH = 2048;
|
34
|
+
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 2048 allowed length.";
|
35
35
|
public final static int MAX_QUERY_STRING_LENGTH = 1024 * 10;
|
36
36
|
public final static String MAX_QUERY_STRING_LENGTH_ERR = "HTTP element QUERY_STRING is longer than the 10240 allowed length.";
|
37
37
|
public final static int MAX_HEADER_LENGTH = 1024 * (80 + 32);
|
@@ -52,7 +52,7 @@ DEF_MAX_LENGTH(FIELD_NAME, 256);
|
|
52
52
|
DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
|
53
53
|
DEF_MAX_LENGTH(REQUEST_URI, 1024 * 12);
|
54
54
|
DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewhere or not */
|
55
|
-
DEF_MAX_LENGTH(REQUEST_PATH,
|
55
|
+
DEF_MAX_LENGTH(REQUEST_PATH, 2048);
|
56
56
|
DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10));
|
57
57
|
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
|
58
58
|
|
data/lib/puma/capistrano.rb
CHANGED
@@ -28,7 +28,12 @@ Capistrano::Configuration.instance.load do
|
|
28
28
|
|
29
29
|
desc 'Restart puma'
|
30
30
|
task :restart, :roles => lambda { puma_role }, :on_no_matching_servers => :continue do
|
31
|
-
|
31
|
+
begin
|
32
|
+
run "cd #{current_path} && #{pumactl_cmd} -S #{state_path} restart"
|
33
|
+
rescue Capistrano::CommandError => ex
|
34
|
+
puts "Failed to restart puma: #{ex}\nAssuming not started."
|
35
|
+
start
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
39
|
desc 'Restart puma (phased restart)'
|
data/lib/puma/cli.rb
CHANGED
data/lib/puma/cluster.rb
CHANGED
@@ -230,6 +230,17 @@ module Puma
|
|
230
230
|
wakeup!
|
231
231
|
end
|
232
232
|
|
233
|
+
Signal.trap "TTIN" do
|
234
|
+
@options[:workers] += 1
|
235
|
+
wakeup!
|
236
|
+
end
|
237
|
+
|
238
|
+
Signal.trap "TTOU" do
|
239
|
+
@options[:workers] -= 1 if @options[:workers] >= 2
|
240
|
+
@workers.last.term
|
241
|
+
wakeup!
|
242
|
+
end
|
243
|
+
|
233
244
|
master_pid = Process.pid
|
234
245
|
|
235
246
|
Signal.trap "SIGTERM" do
|
data/lib/puma/compat.rb
CHANGED
@@ -6,6 +6,13 @@ class String
|
|
6
6
|
end
|
7
7
|
|
8
8
|
unless method_defined? :byteslice
|
9
|
-
|
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
|
16
|
+
end
|
10
17
|
end
|
11
18
|
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.7.0".freeze
|
32
|
+
CODE_NAME = "Earl of Sandwich Partition"
|
33
33
|
|
34
34
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
35
35
|
|
data/lib/puma/daemon_ext.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
module Process
|
2
|
+
|
3
|
+
# This overrides the default version because it is broken if it
|
4
|
+
# exists.
|
5
|
+
|
2
6
|
def self.daemon(nochdir=false, noclose=false)
|
3
7
|
exit if fork # Parent exits, child continues.
|
4
8
|
|
@@ -16,5 +20,5 @@ module Process
|
|
16
20
|
end
|
17
21
|
|
18
22
|
0
|
19
|
-
end
|
23
|
+
end
|
20
24
|
end
|
data/lib/puma/minissl.rb
CHANGED
@@ -27,15 +27,23 @@ module Puma
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def engine_read_all
|
31
|
+
output = @engine.read
|
32
|
+
while output and additional_output = @engine.read
|
33
|
+
output << additional_output
|
34
|
+
end
|
35
|
+
output
|
36
|
+
end
|
37
|
+
|
30
38
|
def read_nonblock(size)
|
31
39
|
while true
|
32
|
-
output =
|
40
|
+
output = engine_read_all
|
33
41
|
return output if output
|
34
42
|
|
35
43
|
data = @socket.read_nonblock(size)
|
36
44
|
|
37
45
|
@engine.inject(data)
|
38
|
-
output =
|
46
|
+
output = engine_read_all
|
39
47
|
|
40
48
|
return output if output
|
41
49
|
|
data/lib/puma/puma_http11.jar
CHANGED
Binary file
|
data/lib/puma/reactor.rb
CHANGED
@@ -18,11 +18,24 @@ module Puma
|
|
18
18
|
@sockets = [@ready]
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
private
|
22
|
+
|
23
|
+
def run_internal
|
22
24
|
sockets = @sockets
|
23
25
|
|
24
26
|
while true
|
25
|
-
|
27
|
+
begin
|
28
|
+
ready = IO.select sockets, nil, nil, @sleep_for
|
29
|
+
rescue IOError => e
|
30
|
+
if sockets.any? { |socket| socket.closed? }
|
31
|
+
STDERR.puts "Error in select: #{e.message} (#{e.class})"
|
32
|
+
STDERR.puts e.backtrace
|
33
|
+
sockets = sockets.reject { |socket| socket.closed? }
|
34
|
+
retry
|
35
|
+
else
|
36
|
+
raise
|
37
|
+
end
|
38
|
+
end
|
26
39
|
|
27
40
|
if ready and reads = ready[0]
|
28
41
|
reads.each do |c|
|
@@ -95,23 +108,30 @@ module Puma
|
|
95
108
|
end
|
96
109
|
end
|
97
110
|
end
|
111
|
+
end
|
112
|
+
|
113
|
+
public
|
114
|
+
|
115
|
+
def run
|
116
|
+
run_internal
|
98
117
|
ensure
|
99
118
|
@trigger.close
|
100
119
|
@ready.close
|
101
120
|
end
|
102
121
|
|
103
122
|
def run_in_thread
|
104
|
-
@thread = Thread.new
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
123
|
+
@thread = Thread.new do
|
124
|
+
begin
|
125
|
+
run_internal
|
126
|
+
rescue StandardError => e
|
127
|
+
STDERR.puts "Error in reactor loop escaped: #{e.message} (#{e.class})"
|
128
|
+
STDERR.puts e.backtrace
|
129
|
+
retry
|
130
|
+
ensure
|
131
|
+
@trigger.close
|
132
|
+
@ready.close
|
113
133
|
end
|
114
|
-
|
134
|
+
end
|
115
135
|
end
|
116
136
|
|
117
137
|
def calculate_sleep
|
data/lib/puma/server.rb
CHANGED
data/test/test_http11.rb
CHANGED
@@ -21,7 +21,7 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
21
21
|
assert_equal '/', req['REQUEST_PATH']
|
22
22
|
assert_equal 'HTTP/1.1', req['HTTP_VERSION']
|
23
23
|
assert_equal '/', req['REQUEST_URI']
|
24
|
-
assert_equal 'GET', req['REQUEST_METHOD']
|
24
|
+
assert_equal 'GET', req['REQUEST_METHOD']
|
25
25
|
assert_nil req['FRAGMENT']
|
26
26
|
assert_nil req['QUERY_STRING']
|
27
27
|
|
@@ -81,7 +81,26 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
81
81
|
|
82
82
|
return res
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
|
+
def test_max_uri_path_length
|
86
|
+
parser = HttpParser.new
|
87
|
+
req = {}
|
88
|
+
|
89
|
+
# Support URI path length to a max of 2048
|
90
|
+
path = "/" + rand_data(1000, 100)
|
91
|
+
http = "GET #{path} HTTP/1.1\r\n\r\n"
|
92
|
+
parser.execute(req, http, 0)
|
93
|
+
assert_equal path, req['REQUEST_PATH']
|
94
|
+
parser.reset
|
95
|
+
|
96
|
+
# Raise exception if URI path length > 2048
|
97
|
+
path = "/" + rand_data(2048, 100)
|
98
|
+
http = "GET #{path} HTTP/1.1\r\n\r\n"
|
99
|
+
assert_raises Puma::HttpParserError do
|
100
|
+
parser.execute(req, http, 0)
|
101
|
+
parser.reset
|
102
|
+
end
|
103
|
+
end
|
85
104
|
|
86
105
|
def test_horrible_queries
|
87
106
|
parser = HttpParser.new
|
@@ -38,8 +38,6 @@ exec /bin/bash <<'EOT'
|
|
38
38
|
# set HOME to the setuid user's home, there doesn't seem to be a better, portable way
|
39
39
|
export HOME="$(eval echo ~$(id -un))"
|
40
40
|
|
41
|
-
cd $app
|
42
|
-
|
43
41
|
if [ -d "$HOME/.rbenv/bin" ]; then
|
44
42
|
export PATH="$HOME/.rbenv/bin:$PATH"
|
45
43
|
elif [ -f /etc/profile.d/rvm.sh ]; then
|
@@ -57,8 +55,9 @@ exec /bin/bash <<'EOT'
|
|
57
55
|
# chruby 2.0.0
|
58
56
|
fi
|
59
57
|
|
58
|
+
cd $app
|
60
59
|
logger -t puma "Starting server: $app"
|
61
60
|
|
62
|
-
exec bundle exec puma -C config/puma
|
61
|
+
exec bundle exec puma -C config/puma.rb
|
63
62
|
EOT
|
64
|
-
end script
|
63
|
+
end script
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 2.
|
5
|
+
version: 2.7.0
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Evan Phoenix
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|