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.

@@ -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
 
@@ -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";
@@ -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
@@ -245,9 +245,10 @@ module Puma
245
245
  end
246
246
  end
247
247
 
248
- def localhost_addresses
249
- addrs = TCPSocket.gethostbyname "localhost"
250
- addrs[3..-1].uniq
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
- localhost_addresses.each do |addr|
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
- localhost_addresses.each do |addr|
302
+ loopback_addresses.each do |addr|
302
303
  add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
303
304
  end
304
305
  return
@@ -111,6 +111,7 @@ module Puma
111
111
  begin
112
112
  @io.close
113
113
  rescue IOError
114
+ Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
114
115
  end
115
116
  end
116
117
 
@@ -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 = "puma: cluster worker #{index}: #{master}"
232
- title << " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
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
@@ -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
@@ -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.9.1".freeze
99
- CODE_NAME = "Private Caller".freeze
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
@@ -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
@@ -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
  #
@@ -80,4 +80,3 @@ module Puma
80
80
  end
81
81
  end
82
82
  end
83
-
@@ -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 = (defined?(Bundler) ? Bundler::ORIGINAL_ENV : ENV.to_h)
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
- ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
229
- redirects[io.to_i] = io.to_i
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 = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
293
- buffer << " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
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
- stop
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