puma 3.9.1-java → 3.10.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.
- checksums.yaml +4 -4
- data/History.md +29 -0
- data/README.md +124 -229
- data/docs/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +102 -37
- data/ext/puma_http11/http11_parser.c +130 -146
- data/ext/puma_http11/http11_parser.rl +9 -9
- data/ext/puma_http11/mini_ssl.c +2 -2
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +13 -16
- data/lib/puma/app/status.rb +8 -0
- data/lib/puma/binder.rb +6 -5
- data/lib/puma/client.rb +1 -0
- data/lib/puma/cluster.rb +8 -2
- data/lib/puma/configuration.rb +3 -2
- data/lib/puma/const.rb +3 -2
- data/lib/puma/control_cli.rb +2 -2
- data/lib/puma/dsl.rb +10 -0
- data/lib/puma/jruby_restart.rb +0 -1
- data/lib/puma/launcher.rb +31 -14
- data/lib/puma/minissl.rb +19 -25
- data/lib/puma/plugin/tmp_restart.rb +0 -1
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/reactor.rb +3 -0
- data/lib/puma/server.rb +25 -19
- data/lib/puma/thread_pool.rb +2 -2
- data/lib/rack/handler/puma.rb +2 -0
- data/tools/jungle/README.md +4 -0
- data/tools/trickletest.rb +1 -1
- metadata +9 -57
- data/.github/issue_template.md +0 -20
- data/DEPLOYMENT.md +0 -91
- data/Gemfile +0 -14
- data/Manifest.txt +0 -78
- data/Rakefile +0 -165
- data/Release.md +0 -9
- data/gemfiles/2.1-Gemfile +0 -12
- data/puma.gemspec +0 -20
@@ -29,7 +29,7 @@ static void snake_upcase_char(char *c)
|
|
29
29
|
/** Machine **/
|
30
30
|
|
31
31
|
%%{
|
32
|
-
|
32
|
+
|
33
33
|
machine puma_parser;
|
34
34
|
|
35
35
|
action mark { MARK(mark, fpc); }
|
@@ -37,7 +37,7 @@ static void snake_upcase_char(char *c)
|
|
37
37
|
|
38
38
|
action start_field { MARK(field_start, fpc); }
|
39
39
|
action snake_upcase_field { snake_upcase_char((char *)fpc); }
|
40
|
-
action write_field {
|
40
|
+
action write_field {
|
41
41
|
parser->field_len = LEN(field_start, fpc);
|
42
42
|
}
|
43
43
|
|
@@ -45,10 +45,10 @@ static void snake_upcase_char(char *c)
|
|
45
45
|
action write_value {
|
46
46
|
parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
|
47
47
|
}
|
48
|
-
action request_method {
|
48
|
+
action request_method {
|
49
49
|
parser->request_method(parser, PTR_TO(mark), LEN(mark, fpc));
|
50
50
|
}
|
51
|
-
action request_uri {
|
51
|
+
action request_uri {
|
52
52
|
parser->request_uri(parser, PTR_TO(mark), LEN(mark, fpc));
|
53
53
|
}
|
54
54
|
action fragment {
|
@@ -56,11 +56,11 @@ static void snake_upcase_char(char *c)
|
|
56
56
|
}
|
57
57
|
|
58
58
|
action start_query { MARK(query_start, fpc); }
|
59
|
-
action query_string {
|
59
|
+
action query_string {
|
60
60
|
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, fpc));
|
61
61
|
}
|
62
62
|
|
63
|
-
action http_version {
|
63
|
+
action http_version {
|
64
64
|
parser->http_version(parser, PTR_TO(mark), LEN(mark, fpc));
|
65
65
|
}
|
66
66
|
|
@@ -68,8 +68,8 @@ static void snake_upcase_char(char *c)
|
|
68
68
|
parser->request_path(parser, PTR_TO(mark), LEN(mark,fpc));
|
69
69
|
}
|
70
70
|
|
71
|
-
action done {
|
72
|
-
parser->body_start = fpc - buffer + 1;
|
71
|
+
action done {
|
72
|
+
parser->body_start = fpc - buffer + 1;
|
73
73
|
parser->header_done(parser, fpc + 1, pe - fpc - 1);
|
74
74
|
fbreak;
|
75
75
|
}
|
@@ -109,7 +109,7 @@ size_t puma_parser_execute(puma_parser *parser, const char *buffer, size_t len,
|
|
109
109
|
pe = buffer+len;
|
110
110
|
|
111
111
|
/* assert(*pe == '\0' && "pointer does not end on NUL"); */
|
112
|
-
assert(pe - p == len - off && "pointers aren't same distance");
|
112
|
+
assert((size_t) (pe - p) == len - off && "pointers aren't same distance");
|
113
113
|
|
114
114
|
%% write exec;
|
115
115
|
|
data/ext/puma_http11/mini_ssl.c
CHANGED
@@ -244,7 +244,7 @@ void raise_error(SSL* ssl, int result) {
|
|
244
244
|
const char* err_str;
|
245
245
|
int err = errno;
|
246
246
|
int ssl_err = SSL_get_error(ssl, result);
|
247
|
-
int verify_err = SSL_get_verify_result(ssl);
|
247
|
+
int verify_err = (int) SSL_get_verify_result(ssl);
|
248
248
|
|
249
249
|
if(SSL_ERROR_SYSCALL == ssl_err) {
|
250
250
|
snprintf(msg, sizeof(msg), "System error: %s - %d", strerror(err), err);
|
@@ -257,7 +257,7 @@ void raise_error(SSL* ssl, int result) {
|
|
257
257
|
err_str, verify_err);
|
258
258
|
|
259
259
|
} else {
|
260
|
-
err = ERR_get_error();
|
260
|
+
err = (int) ERR_get_error();
|
261
261
|
ERR_error_string_n(err, buf, sizeof(buf));
|
262
262
|
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
263
263
|
|
@@ -182,9 +182,6 @@ static final int puma_parser_start = 1;
|
|
182
182
|
static final int puma_parser_first_final = 47;
|
183
183
|
static final int puma_parser_error = 0;
|
184
184
|
|
185
|
-
static final int puma_parser_en_main = 1;
|
186
|
-
|
187
|
-
|
188
185
|
// line 69 "ext/puma_http11/http11_parser.java.rl"
|
189
186
|
|
190
187
|
public static interface ElementCB {
|
@@ -220,7 +217,7 @@ static final int puma_parser_en_main = 1;
|
|
220
217
|
public void init() {
|
221
218
|
cs = 0;
|
222
219
|
|
223
|
-
|
220
|
+
|
224
221
|
// line 225 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
225
222
|
{
|
226
223
|
cs = puma_parser_start;
|
@@ -252,7 +249,7 @@ static final int puma_parser_en_main = 1;
|
|
252
249
|
byte[] data = buffer.bytes();
|
253
250
|
parser.buffer = buffer;
|
254
251
|
|
255
|
-
|
252
|
+
|
256
253
|
// line 257 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
257
254
|
{
|
258
255
|
int _klen;
|
@@ -347,7 +344,7 @@ case 1:
|
|
347
344
|
break;
|
348
345
|
case 3:
|
349
346
|
// line 17 "ext/puma_http11/http11_parser.java.rl"
|
350
|
-
{
|
347
|
+
{
|
351
348
|
parser.field_len = p-parser.field_start;
|
352
349
|
}
|
353
350
|
break;
|
@@ -357,7 +354,7 @@ case 1:
|
|
357
354
|
break;
|
358
355
|
case 5:
|
359
356
|
// line 22 "ext/puma_http11/http11_parser.java.rl"
|
360
|
-
{
|
357
|
+
{
|
361
358
|
if(parser.http_field != null) {
|
362
359
|
parser.http_field.call(parser.data, parser.field_start, parser.field_len, parser.mark, p-parser.mark);
|
363
360
|
}
|
@@ -365,21 +362,21 @@ case 1:
|
|
365
362
|
break;
|
366
363
|
case 6:
|
367
364
|
// line 27 "ext/puma_http11/http11_parser.java.rl"
|
368
|
-
{
|
369
|
-
if(parser.request_method != null)
|
365
|
+
{
|
366
|
+
if(parser.request_method != null)
|
370
367
|
parser.request_method.call(parser.data, parser.mark, p-parser.mark);
|
371
368
|
}
|
372
369
|
break;
|
373
370
|
case 7:
|
374
371
|
// line 31 "ext/puma_http11/http11_parser.java.rl"
|
375
|
-
{
|
372
|
+
{
|
376
373
|
if(parser.request_uri != null)
|
377
374
|
parser.request_uri.call(parser.data, parser.mark, p-parser.mark);
|
378
375
|
}
|
379
376
|
break;
|
380
377
|
case 8:
|
381
378
|
// line 35 "ext/puma_http11/http11_parser.java.rl"
|
382
|
-
{
|
379
|
+
{
|
383
380
|
if(parser.fragment != null)
|
384
381
|
parser.fragment.call(parser.data, parser.mark, p-parser.mark);
|
385
382
|
}
|
@@ -390,14 +387,14 @@ case 1:
|
|
390
387
|
break;
|
391
388
|
case 10:
|
392
389
|
// line 41 "ext/puma_http11/http11_parser.java.rl"
|
393
|
-
{
|
390
|
+
{
|
394
391
|
if(parser.query_string != null)
|
395
392
|
parser.query_string.call(parser.data, parser.query_start, p-parser.query_start);
|
396
393
|
}
|
397
394
|
break;
|
398
395
|
case 11:
|
399
396
|
// line 46 "ext/puma_http11/http11_parser.java.rl"
|
400
|
-
{
|
397
|
+
{
|
401
398
|
if(parser.http_version != null)
|
402
399
|
parser.http_version.call(parser.data, parser.mark, p-parser.mark);
|
403
400
|
}
|
@@ -411,8 +408,8 @@ case 1:
|
|
411
408
|
break;
|
412
409
|
case 13:
|
413
410
|
// line 56 "ext/puma_http11/http11_parser.java.rl"
|
414
|
-
{
|
415
|
-
parser.body_start = p + 1;
|
411
|
+
{
|
412
|
+
parser.body_start = p + 1;
|
416
413
|
if(parser.header_done != null)
|
417
414
|
parser.header_done.call(parser.data, p + 1, pe - p - 1);
|
418
415
|
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
|
@@ -442,7 +439,7 @@ case 5:
|
|
442
439
|
|
443
440
|
parser.cs = cs;
|
444
441
|
parser.nread += (p - off);
|
445
|
-
|
442
|
+
|
446
443
|
assert p <= pe : "buffer overflow after parsing execute";
|
447
444
|
assert parser.nread <= len : "nread longer than length";
|
448
445
|
assert parser.body_start <= len : "body starts after buffer end";
|
data/lib/puma/app/status.rb
CHANGED
@@ -55,6 +55,14 @@ module Puma
|
|
55
55
|
return rack_response(200, OK_STATUS)
|
56
56
|
end
|
57
57
|
|
58
|
+
when /\/gc$/
|
59
|
+
GC.start
|
60
|
+
return rack_response(200, OK_STATUS)
|
61
|
+
|
62
|
+
when /\/gc-stats$/
|
63
|
+
json = "{" + GC.stat.map { |k, v| "\"#{k}\": #{v}" }.join(",") + "}"
|
64
|
+
return rack_response(200, json)
|
65
|
+
|
58
66
|
when /\/stats$/
|
59
67
|
return rack_response(200, @cli.stats)
|
60
68
|
else
|
data/lib/puma/binder.rb
CHANGED
@@ -245,9 +245,10 @@ module Puma
|
|
245
245
|
end
|
246
246
|
end
|
247
247
|
|
248
|
-
def
|
249
|
-
|
250
|
-
|
248
|
+
def loopback_addresses
|
249
|
+
Socket.ip_address_list.select do |addrinfo|
|
250
|
+
addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
|
251
|
+
end.map { |addrinfo| addrinfo.ip_address }.uniq
|
251
252
|
end
|
252
253
|
|
253
254
|
# Tell the server to listen on host +host+, port +port+.
|
@@ -259,7 +260,7 @@ module Puma
|
|
259
260
|
#
|
260
261
|
def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
|
261
262
|
if host == "localhost"
|
262
|
-
|
263
|
+
loopback_addresses.each do |addr|
|
263
264
|
add_tcp_listener addr, port, optimize_for_latency, backlog
|
264
265
|
end
|
265
266
|
return
|
@@ -298,7 +299,7 @@ module Puma
|
|
298
299
|
MiniSSL.check
|
299
300
|
|
300
301
|
if host == "localhost"
|
301
|
-
|
302
|
+
loopback_addresses.each do |addr|
|
302
303
|
add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
|
303
304
|
end
|
304
305
|
return
|
data/lib/puma/client.rb
CHANGED
data/lib/puma/cluster.rb
CHANGED
@@ -224,12 +224,13 @@ module Puma
|
|
224
224
|
begin
|
225
225
|
@wakeup.write "!" unless @wakeup.closed?
|
226
226
|
rescue SystemCallError, IOError
|
227
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
227
228
|
end
|
228
229
|
end
|
229
230
|
|
230
231
|
def worker(index, master)
|
231
|
-
title
|
232
|
-
title
|
232
|
+
title = "puma: cluster worker #{index}: #{master}"
|
233
|
+
title += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
233
234
|
$0 = title
|
234
235
|
|
235
236
|
Signal.trap "SIGINT", "IGNORE"
|
@@ -267,6 +268,7 @@ module Puma
|
|
267
268
|
begin
|
268
269
|
@worker_write << "b#{Process.pid}\n"
|
269
270
|
rescue SystemCallError, IOError
|
271
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
270
272
|
STDERR.puts "Master seems to have exited, exiting."
|
271
273
|
return
|
272
274
|
end
|
@@ -282,6 +284,7 @@ module Puma
|
|
282
284
|
payload = %Q!#{base_payload}{ "backlog":#{b}, "running":#{r} }\n!
|
283
285
|
io << payload
|
284
286
|
rescue IOError
|
287
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
285
288
|
break
|
286
289
|
end
|
287
290
|
end
|
@@ -372,7 +375,10 @@ module Puma
|
|
372
375
|
log "Early termination of worker"
|
373
376
|
exit! 0
|
374
377
|
else
|
378
|
+
stop_workers
|
375
379
|
stop
|
380
|
+
|
381
|
+
raise SignalException, "SIGTERM"
|
376
382
|
end
|
377
383
|
end
|
378
384
|
end
|
data/lib/puma/configuration.rb
CHANGED
@@ -183,7 +183,8 @@ module Puma
|
|
183
183
|
:environment => ->{ ENV['RACK_ENV'] || "development" },
|
184
184
|
:rackup => DefaultRackup,
|
185
185
|
:logger => STDOUT,
|
186
|
-
:persistent_timeout => Const::PERSISTENT_TIMEOUT
|
186
|
+
:persistent_timeout => Const::PERSISTENT_TIMEOUT,
|
187
|
+
:first_data_timeout => Const::FIRST_DATA_TIMEOUT
|
187
188
|
}
|
188
189
|
end
|
189
190
|
|
@@ -340,7 +341,7 @@ module Puma
|
|
340
341
|
end
|
341
342
|
|
342
343
|
if bytes
|
343
|
-
token = ""
|
344
|
+
token = "".dup
|
344
345
|
bytes.each_byte { |b| token << b.to_s(16) }
|
345
346
|
else
|
346
347
|
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
data/lib/puma/const.rb
CHANGED
@@ -53,6 +53,7 @@ module Puma
|
|
53
53
|
415 => 'Unsupported Media Type',
|
54
54
|
416 => 'Range Not Satisfiable',
|
55
55
|
417 => 'Expectation Failed',
|
56
|
+
418 => 'I\'m A Teapot',
|
56
57
|
422 => 'Unprocessable Entity',
|
57
58
|
423 => 'Locked',
|
58
59
|
424 => 'Failed Dependency',
|
@@ -95,8 +96,8 @@ module Puma
|
|
95
96
|
# too taxing on performance.
|
96
97
|
module Const
|
97
98
|
|
98
|
-
PUMA_VERSION = VERSION = "3.
|
99
|
-
CODE_NAME = "
|
99
|
+
PUMA_VERSION = VERSION = "3.10.0".freeze
|
100
|
+
CODE_NAME = "Russell's Teapot".freeze
|
100
101
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
101
102
|
|
102
103
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
data/lib/puma/control_cli.rb
CHANGED
@@ -9,7 +9,7 @@ require 'socket'
|
|
9
9
|
module Puma
|
10
10
|
class ControlCLI
|
11
11
|
|
12
|
-
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
|
12
|
+
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
|
13
13
|
|
14
14
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
15
15
|
@state = nil
|
@@ -169,7 +169,7 @@ module Puma
|
|
169
169
|
end
|
170
170
|
|
171
171
|
message "Command #{@command} sent success"
|
172
|
-
message response.last if @command == "stats"
|
172
|
+
message response.last if @command == "stats" || @command == "gc-stats"
|
173
173
|
end
|
174
174
|
|
175
175
|
@server.close
|
data/lib/puma/dsl.rb
CHANGED
@@ -118,6 +118,10 @@ module Puma
|
|
118
118
|
@options[:binds] << url
|
119
119
|
end
|
120
120
|
|
121
|
+
def clear_binds!
|
122
|
+
@options[:binds] = []
|
123
|
+
end
|
124
|
+
|
121
125
|
# Define the TCP port to bind to. Use +bind+ for more advanced options.
|
122
126
|
#
|
123
127
|
def port(port, host=nil)
|
@@ -132,6 +136,12 @@ module Puma
|
|
132
136
|
@options[:persistent_timeout] = seconds
|
133
137
|
end
|
134
138
|
|
139
|
+
# Define how long the tcp socket stays open, if no data has been received
|
140
|
+
#
|
141
|
+
def first_data_timeout(seconds)
|
142
|
+
@options[:first_data_timeout] = seconds
|
143
|
+
end
|
144
|
+
|
135
145
|
# Work around leaky apps that leave garbage in Thread locals
|
136
146
|
# across requests
|
137
147
|
#
|
data/lib/puma/jruby_restart.rb
CHANGED
data/lib/puma/launcher.rb
CHANGED
@@ -163,7 +163,16 @@ module Puma
|
|
163
163
|
|
164
164
|
# Run the server. This blocks until the server is stopped
|
165
165
|
def run
|
166
|
-
previous_env =
|
166
|
+
previous_env =
|
167
|
+
if defined?(Bundler)
|
168
|
+
env = Bundler::ORIGINAL_ENV.dup
|
169
|
+
# add -rbundler/setup so we load from Gemfile when restarting
|
170
|
+
bundle = "-rbundler/setup"
|
171
|
+
env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ") unless env["RUBYOPT"].to_s.include?(bundle)
|
172
|
+
env
|
173
|
+
else
|
174
|
+
ENV.to_h
|
175
|
+
end
|
167
176
|
|
168
177
|
@config.clamp
|
169
178
|
|
@@ -225,8 +234,8 @@ module Puma
|
|
225
234
|
else
|
226
235
|
redirects = {:close_others => true}
|
227
236
|
@binder.listeners.each_with_index do |(l, io), i|
|
228
|
-
|
229
|
-
|
237
|
+
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
238
|
+
redirects[io.to_i] = io.to_i
|
230
239
|
end
|
231
240
|
|
232
241
|
argv = restart_args
|
@@ -289,8 +298,8 @@ module Puma
|
|
289
298
|
end
|
290
299
|
|
291
300
|
def title
|
292
|
-
buffer
|
293
|
-
buffer
|
301
|
+
buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
|
302
|
+
buffer += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
294
303
|
buffer
|
295
304
|
end
|
296
305
|
|
@@ -383,12 +392,28 @@ module Puma
|
|
383
392
|
|
384
393
|
begin
|
385
394
|
Signal.trap "SIGTERM" do
|
386
|
-
|
395
|
+
graceful_stop
|
396
|
+
|
397
|
+
raise SignalException, "SIGTERM"
|
387
398
|
end
|
388
399
|
rescue Exception
|
389
400
|
log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
|
390
401
|
end
|
391
402
|
|
403
|
+
begin
|
404
|
+
Signal.trap "SIGINT" do
|
405
|
+
if Puma.jruby?
|
406
|
+
@status = :exit
|
407
|
+
graceful_stop
|
408
|
+
exit
|
409
|
+
end
|
410
|
+
|
411
|
+
stop
|
412
|
+
end
|
413
|
+
rescue Exception
|
414
|
+
log "*** SIGINT not implemented, signal based gracefully stopping unavailable!"
|
415
|
+
end
|
416
|
+
|
392
417
|
begin
|
393
418
|
Signal.trap "SIGHUP" do
|
394
419
|
if @runner.redirected_io?
|
@@ -400,14 +425,6 @@ module Puma
|
|
400
425
|
rescue Exception
|
401
426
|
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
402
427
|
end
|
403
|
-
|
404
|
-
if Puma.jruby?
|
405
|
-
Signal.trap("INT") do
|
406
|
-
@status = :exit
|
407
|
-
graceful_stop
|
408
|
-
exit
|
409
|
-
end
|
410
|
-
end
|
411
428
|
end
|
412
429
|
end
|
413
430
|
end
|