puma 2.12.3 → 2.13.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8fb289c9463eb0aec389606cde7abca74b3ba737
4
- data.tar.gz: 0f81b87b1bd9c0fa43d9c67e6d8b5c2f4a4b97a9
3
+ metadata.gz: adcb4384f1d28b84c63041a1b78402482a6db2ce
4
+ data.tar.gz: ce554d8a2caa636a2a9607d4a2c4aebee5e494e6
5
5
  SHA512:
6
- metadata.gz: bf53fee269a717c206e9031cfb26c6e7924eb346d7d17f5accf57d858813fb6302aecb1832385b2a87a94e68f452fae50f218cfe2f941617df8370c712e20d9f
7
- data.tar.gz: 92daf0ecf12fb7abda0655461ec72bff29f96dbf955f3434049f00e1e4de87b4b2672db36f03fe62ed36b0df0ea28305bd2dab80fa3de90ac3742a5954a42397
6
+ metadata.gz: 297c51791e245bb2da548687422d1558d4996006a90d6774a792e7d7ba5f274584c17a8779324650ef369c2e22f3c1d2a1fe297e248b12e593bf8f9182b6ef03
7
+ data.tar.gz: c80e343900046c22ab04f769fe93f23a21ee049ced503651e2ce308318442de6ede044ea9427d0f385c183435ad9f6c63289a58220f1df854fdcf077e50d1553
@@ -1,3 +1,22 @@
1
+ === 2.13.0 / 2015-08-14
2
+
3
+ * 1 minor feature:
4
+ * Add before_fork hooks option.
5
+
6
+ * 3 bug fixes:
7
+ * Check for OPENSSL_NO_ECDH before using ECDH
8
+ * Eliminate logging overhead from JRuby SSL
9
+ * Prefer cli options over config file ones. Fixes #669
10
+
11
+ * 1 deprecation:
12
+ * Add deprecation warning to capistrano.rb. Fixes #673
13
+
14
+ * 4 PRs merged:
15
+ * Merge pull request #668 from kcollignon/patch-1
16
+ * Merge pull request #754 from nathansamson/before_boot
17
+ * Merge pull request #759 from BenV/fix-centos6-build
18
+ * Merge pull request #761 from looker/no-log
19
+
1
20
  === 2.12.3 / 2015-08-03
2
21
 
3
22
  * 8 minor bugs fixed:
data/README.md CHANGED
@@ -248,7 +248,7 @@ and then
248
248
  $ bundle exec cap puma:start
249
249
  $ bundle exec cap puma:restart
250
250
  $ bundle exec cap puma:stop
251
- $ bundle exec cap puma:phased_restart
251
+ $ bundle exec cap puma:phased-restart
252
252
  ```
253
253
 
254
254
  ## Contributing
@@ -147,11 +147,13 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
147
147
  DH *dh = get_dh1024();
148
148
  SSL_CTX_set_tmp_dh(ctx, dh);
149
149
 
150
+ #ifndef OPENSSL_NO_ECDH
150
151
  EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
151
152
  if (ecdh) {
152
153
  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
153
154
  EC_KEY_free(ecdh);
154
155
  }
156
+ #endif
155
157
 
156
158
  ssl = SSL_new(ctx);
157
159
  conn->ssl = ssl;
@@ -1,7 +1,6 @@
1
1
  package org.jruby.puma;
2
2
 
3
3
  import org.jruby.Ruby;
4
- import org.jruby.RubyBoolean;
5
4
  import org.jruby.RubyClass;
6
5
  import org.jruby.RubyModule;
7
6
  import org.jruby.RubyObject;
@@ -39,9 +38,6 @@ public class MiniSSL extends RubyObject {
39
38
  }
40
39
  };
41
40
 
42
- // set to true to switch on our low-fi trace logging
43
- private static boolean DEBUG = false;
44
-
45
41
  public static void createMiniSSL(Ruby runtime) {
46
42
  RubyModule mPuma = runtime.defineModule("Puma");
47
43
  RubyModule ssl = mPuma.defineModuleUnder("MiniSSL");
@@ -170,12 +166,7 @@ public class MiniSSL extends RubyObject {
170
166
  public IRubyObject inject(IRubyObject arg) {
171
167
  try {
172
168
  byte[] bytes = arg.convertToString().getBytes();
173
-
174
- log("Net Data post pre-inject: " + inboundNetData);
175
169
  inboundNetData.put(bytes);
176
- log("Net Data post post-inject: " + inboundNetData);
177
-
178
- log("inject(): " + bytes.length + " encrypted bytes from request");
179
170
  return this;
180
171
  } catch (Exception e) {
181
172
  e.printStackTrace();
@@ -205,8 +196,6 @@ public class MiniSSL extends RubyObject {
205
196
 
206
197
  switch (res.getStatus()) {
207
198
  case BUFFER_OVERFLOW:
208
- log("SSLOp#doRun(): overflow");
209
- log("SSLOp#doRun(): dst data at overflow: " + dst);
210
199
  // increase the buffer size to accommodate the overflowing data
211
200
  int newSize = Math.max(engine.getSession().getPacketBufferSize(), engine.getSession().getApplicationBufferSize());
212
201
  dst.resize(newSize + dst.position());
@@ -214,8 +203,6 @@ public class MiniSSL extends RubyObject {
214
203
  retryOp = true;
215
204
  break;
216
205
  case BUFFER_UNDERFLOW:
217
- log("SSLOp#doRun(): underflow");
218
- log("SSLOp#doRun(): src data at underflow: " + src);
219
206
  // need to wait for more data to come in before we retry
220
207
  retryOp = false;
221
208
  break;
@@ -245,25 +232,18 @@ public class MiniSSL extends RubyObject {
245
232
  return getRuntime().getNil();
246
233
  }
247
234
 
248
- log("read(): inboundNetData prepped for read: " + inboundNetData);
249
-
250
235
  MiniSSLBuffer inboundAppData = new MiniSSLBuffer(engine.getSession().getApplicationBufferSize());
251
- SSLEngineResult res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
252
- log("read(): after initial unwrap", engine, res);
253
-
254
- log("read(): Net Data post unwrap: " + inboundNetData);
236
+ doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
255
237
 
256
238
  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
257
239
  boolean done = false;
258
240
  while (!done) {
259
241
  switch (handshakeStatus) {
260
242
  case NEED_WRAP:
261
- res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
262
- log("read(): after handshake wrap", engine, res);
243
+ doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
263
244
  break;
264
245
  case NEED_UNWRAP:
265
- res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
266
- log("read(): after handshake unwrap", engine, res);
246
+ SSLEngineResult res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
267
247
  if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
268
248
  // need more data before we can shake more hands
269
249
  done = true;
@@ -276,13 +256,9 @@ public class MiniSSL extends RubyObject {
276
256
  }
277
257
 
278
258
  if (inboundNetData.hasRemaining()) {
279
- log("Net Data post pre-compact: " + inboundNetData);
280
259
  inboundNetData.compact();
281
- log("Net Data post post-compact: " + inboundNetData);
282
260
  } else {
283
- log("Net Data post pre-reset: " + inboundNetData);
284
261
  inboundNetData.clear();
285
- log("Net Data post post-reset: " + inboundNetData);
286
262
  }
287
263
 
288
264
  ByteList appDataByteList = inboundAppData.asByteList();
@@ -292,54 +268,15 @@ public class MiniSSL extends RubyObject {
292
268
 
293
269
  RubyString str = getRuntime().newString("");
294
270
  str.setValue(appDataByteList);
295
-
296
- logPlain("\n");
297
- log("read(): begin dump of request data >>>>\n");
298
- if (str.asJavaString().getBytes().length < 1000) {
299
- logPlain(str.asJavaString() + "\n");
300
- }
301
- logPlain("Num bytes: " + str.asJavaString().getBytes().length + "\n");
302
- log("read(): end dump of request data <<<<\n");
303
271
  return str;
304
272
  } catch (Exception e) {
305
- if (DEBUG) {
306
- e.printStackTrace();
307
- }
308
273
  throw getRuntime().newEOFError(e.getMessage());
309
274
  }
310
275
  }
311
276
 
312
- private static void log(String str, SSLEngine engine, SSLEngineResult result) {
313
- if (DEBUG) {
314
- log(str + " " + result.getStatus() + "/" + engine.getHandshakeStatus() +
315
- "---bytes consumed: " + result.bytesConsumed() +
316
- ", bytes produced: " + result.bytesProduced());
317
- }
318
- }
319
-
320
- private static void log(String str) {
321
- if (DEBUG) {
322
- System.out.println("MiniSSL.java: " + str);
323
- }
324
- }
325
-
326
- private static void logPlain(String str) {
327
- if (DEBUG) {
328
- System.out.println(str);
329
- }
330
- }
331
-
332
277
  @JRubyMethod
333
278
  public IRubyObject write(IRubyObject arg) {
334
279
  try {
335
- log("write(): begin dump of response data >>>>\n");
336
- logPlain("\n");
337
- if (arg.asJavaString().getBytes().length < 1000) {
338
- logPlain(arg.asJavaString() + "\n");
339
- }
340
- logPlain("Num bytes: " + arg.asJavaString().getBytes().length + "\n");
341
- log("write(): end dump of response data <<<<\n");
342
-
343
280
  byte[] bls = arg.convertToString().getBytes();
344
281
  outboundAppData = new MiniSSLBuffer(bls);
345
282
 
@@ -365,9 +302,7 @@ public class MiniSSL extends RubyObject {
365
302
  }
366
303
 
367
304
  outboundNetData.clear();
368
- SSLEngineResult res = doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
369
- log("extract(): bytes consumed: " + res.bytesConsumed() + "\n");
370
- log("extract(): bytes produced: " + res.bytesProduced() + "\n");
305
+ doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
371
306
  dataByteList = outboundNetData.asByteList();
372
307
  if (dataByteList == null) {
373
308
  return getRuntime().getNil();
@@ -376,8 +311,6 @@ public class MiniSSL extends RubyObject {
376
311
  RubyString str = getRuntime().newString("");
377
312
  str.setValue(dataByteList);
378
313
 
379
- log("extract(): " + dataByteList.getRealSize() + " encrypted bytes for response");
380
-
381
314
  return str;
382
315
  } catch (Exception e) {
383
316
  e.printStackTrace();
@@ -1,3 +1,5 @@
1
+ $stderr.puts "DEPRECATED: To manage puma with capistrano, use https://github.com/seuros/capistrano-puma"
2
+
1
3
  Capistrano::Configuration.instance.load do
2
4
 
3
5
  # Ensure the tmp/sockets directory is created by the deploy:setup task and
@@ -96,7 +96,7 @@ module Puma
96
96
  end
97
97
 
98
98
  def env
99
- @options[:environment] || ENV['RACK_ENV'] || 'development'
99
+ @cli_options[:environment] || ENV['RACK_ENV'] || 'development'
100
100
  end
101
101
 
102
102
  def write_state
@@ -289,43 +289,34 @@ module Puma
289
289
  end
290
290
 
291
291
  def find_config
292
- if @options[:config_file] == '-'
293
- @options[:config_file] = nil
292
+ if @cli_options[:config_file] == '-'
293
+ @cli_options[:config_file] = nil
294
294
  else
295
- @options[:config_file] ||= %W(config/puma/#{env}.rb config/puma.rb).find { |f| File.exist?(f) }
295
+ @cli_options[:config_file] ||= %W(config/puma/#{env}.rb config/puma.rb).find { |f| File.exist?(f) }
296
296
  end
297
297
  end
298
298
 
299
299
  # Build the OptionParser object to handle the available options.
300
300
  #
301
+
301
302
  def setup_options
302
- @options = {
303
- :min_threads => 0,
304
- :max_threads => 16,
305
- :quiet => false,
306
- :debug => false,
307
- :binds => [],
308
- :workers => 0,
309
- :daemon => false,
310
- :before_worker_shutdown => [],
311
- :before_worker_boot => [],
312
- :before_worker_fork => [],
313
- :after_worker_boot => []
303
+ @cli_options = {
304
+ :binds => []
314
305
  }
315
306
 
316
307
  @parser = OptionParser.new do |o|
317
308
  o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
318
- @options[:binds] << arg
309
+ @cli_options[:binds] << arg
319
310
  end
320
311
 
321
312
  o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
322
- @options[:config_file] = arg
313
+ @cli_options[:config_file] = arg
323
314
  end
324
315
 
325
316
  o.on "--control URL", "The bind url to use for the control server",
326
317
  "Use 'auto' to use temp unix server" do |arg|
327
318
  if arg
328
- @options[:control_url] = arg
319
+ @cli_options[:control_url] = arg
329
320
  elsif jruby?
330
321
  unsupported "No default url available on JRuby"
331
322
  end
@@ -333,26 +324,26 @@ module Puma
333
324
 
334
325
  o.on "--control-token TOKEN",
335
326
  "The token to use as authentication for the control server" do |arg|
336
- @options[:control_auth_token] = arg
327
+ @cli_options[:control_auth_token] = arg
337
328
  end
338
329
 
339
330
  o.on "-d", "--daemon", "Daemonize the server into the background" do
340
- @options[:daemon] = true
341
- @options[:quiet] = true
331
+ @cli_options[:daemon] = true
332
+ @cli_options[:quiet] = true
342
333
  end
343
334
 
344
335
  o.on "--debug", "Log lowlevel debugging information" do
345
- @options[:debug] = true
336
+ @cli_options[:debug] = true
346
337
  end
347
338
 
348
339
  o.on "--dir DIR", "Change to DIR before starting" do |d|
349
- @options[:directory] = d.to_s
350
- @options[:worker_directory] = d.to_s
340
+ @cli_options[:directory] = d.to_s
341
+ @cli_options[:worker_directory] = d.to_s
351
342
  end
352
343
 
353
344
  o.on "-e", "--environment ENVIRONMENT",
354
345
  "The environment to run the Rack app on (default development)" do |arg|
355
- @options[:environment] = arg
346
+ @cli_options[:environment] = arg
356
347
  end
357
348
 
358
349
  o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
@@ -361,48 +352,48 @@ module Puma
361
352
 
362
353
  o.on "-p", "--port PORT", "Define the TCP port to bind to",
363
354
  "Use -b for more advanced options" do |arg|
364
- @options[:binds] << "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
355
+ @cli_options[:binds] << "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
365
356
  end
366
357
 
367
358
  o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
368
- @options[:pidfile] = arg
359
+ @cli_options[:pidfile] = arg
369
360
  end
370
361
 
371
362
  o.on "--preload", "Preload the app. Cluster mode only" do
372
- @options[:preload_app] = true
363
+ @cli_options[:preload_app] = true
373
364
  end
374
365
 
375
366
  o.on "--prune-bundler", "Prune out the bundler env if possible" do
376
- @options[:prune_bundler] = true
367
+ @cli_options[:prune_bundler] = true
377
368
  end
378
369
 
379
370
  o.on "-q", "--quiet", "Quiet down the output" do
380
- @options[:quiet] = true
371
+ @cli_options[:quiet] = true
381
372
  end
382
373
 
383
374
  o.on "-R", "--restart-cmd CMD",
384
375
  "The puma command to run during a hot restart",
385
376
  "Default: inferred" do |cmd|
386
- @options[:restart_cmd] = cmd
377
+ @cli_options[:restart_cmd] = cmd
387
378
  end
388
379
 
389
380
  o.on "-S", "--state PATH", "Where to store the state details" do |arg|
390
- @options[:state] = arg
381
+ @cli_options[:state] = arg
391
382
  end
392
383
 
393
384
  o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
394
385
  min, max = arg.split(":")
395
386
  if max
396
- @options[:min_threads] = min
397
- @options[:max_threads] = max
387
+ @cli_options[:min_threads] = min
388
+ @cli_options[:max_threads] = max
398
389
  else
399
- @options[:min_threads] = 0
400
- @options[:max_threads] = arg
390
+ @cli_options[:min_threads] = 0
391
+ @cli_options[:max_threads] = arg
401
392
  end
402
393
  end
403
394
 
404
395
  o.on "--tcp-mode", "Run the app in raw TCP mode instead of HTTP mode" do
405
- @options[:mode] = :tcp
396
+ @cli_options[:mode] = :tcp
406
397
  end
407
398
 
408
399
  o.on "-V", "--version", "Print the version information" do
@@ -412,11 +403,11 @@ module Puma
412
403
 
413
404
  o.on "-w", "--workers COUNT",
414
405
  "Activate cluster mode: How many worker processes to create" do |arg|
415
- @options[:workers] = arg.to_i
406
+ @cli_options[:workers] = arg.to_i
416
407
  end
417
408
 
418
409
  o.on "--tag NAME", "Additional text to display in process listing" do |arg|
419
- @options[:tag] = arg
410
+ @cli_options[:tag] = arg
420
411
  end
421
412
 
422
413
  o.banner = "puma <options> <rackup file>"
@@ -438,7 +429,7 @@ module Puma
438
429
 
439
430
  if s_env.ino == s_pwd.ino and (jruby? or s_env.dev == s_pwd.dev)
440
431
  @restart_dir = dir
441
- @options[:worker_directory] = dir
432
+ @cli_options[:worker_directory] = dir
442
433
  end
443
434
  end
444
435
 
@@ -528,17 +519,19 @@ module Puma
528
519
  def parse_options
529
520
  @parser.parse! @argv
530
521
 
531
- @options[:rackup] = @argv.shift if @argv.last
522
+ @cli_options[:rackup] = @argv.shift if @argv.last
532
523
 
533
524
  find_config
534
525
 
535
- @config = Puma::Configuration.new @options
526
+ @config = Puma::Configuration.new @cli_options
536
527
 
537
528
  # Advertise the Configuration
538
529
  Puma.cli_config = @config
539
530
 
540
531
  @config.load
541
532
 
533
+ @options = @config.options
534
+
542
535
  if clustered? && (jruby? || windows?)
543
536
  unsupported 'worker mode not supported on JRuby or Windows'
544
537
  end
@@ -379,6 +379,10 @@ module Puma
379
379
  @cli.write_state
380
380
 
381
381
  @master_read, @worker_write = read, @wakeup
382
+
383
+ hooks = @options[:before_fork]
384
+ hooks.each { |h| h.call }
385
+
382
386
  spawn_workers
383
387
 
384
388
  Signal.trap "SIGINT" do
@@ -15,26 +15,50 @@ module Puma
15
15
  include ConfigDefault
16
16
 
17
17
  def initialize(options)
18
- @options = options
19
- @options[:mode] ||= :http
20
- @options[:binds] ||= []
21
- @options[:on_restart] ||= []
22
- @options[:before_worker_shutdown] ||= []
23
- @options[:before_worker_boot] ||= []
24
- @options[:before_worker_fork] ||= []
25
- @options[:after_worker_boot] ||= []
26
- @options[:worker_timeout] ||= DefaultWorkerTimeout
27
- @options[:worker_shutdown_timeout] ||= DefaultWorkerShutdownTimeout
18
+ @cli_options = options
19
+
20
+ @conf = {}
21
+ @conf[:mode] ||= :http
22
+ @conf[:binds] ||= []
23
+ @conf[:on_restart] ||= []
24
+ @conf[:before_fork] ||= []
25
+ @conf[:before_worker_shutdown] ||= []
26
+ @conf[:before_worker_boot] ||= []
27
+ @conf[:before_worker_fork] ||= []
28
+ @conf[:after_worker_boot] ||= []
29
+ @conf[:worker_timeout] ||= DefaultWorkerTimeout
30
+ @conf[:worker_shutdown_timeout] ||= DefaultWorkerShutdownTimeout
31
+
32
+ @options = {}
28
33
  end
29
34
 
30
35
  attr_reader :options
31
36
 
32
37
  def initialize_copy(other)
33
- @options = @options.dup
38
+ @conf = @conf.dup
39
+ end
40
+
41
+ def default_options
42
+ {
43
+ :min_threads => 0,
44
+ :max_threads => 16,
45
+ :quiet => false,
46
+ :debug => false,
47
+ :binds => [],
48
+ :workers => 0,
49
+ :daemon => false,
50
+ }
34
51
  end
35
52
 
36
53
  def load
37
- DSL.load(@options, @options[:config_file])
54
+ DSL.load(@conf, @cli_options[:config_file])
55
+
56
+ # Load the options in the right priority
57
+ #
58
+ @options = {}
59
+ @options.merge! default_options
60
+ @options.merge! @conf
61
+ @options.merge! @cli_options
38
62
 
39
63
  setup_binds
40
64
  setup_control
@@ -99,8 +99,8 @@ module Puma
99
99
  # too taxing on performance.
100
100
  module Const
101
101
 
102
- PUMA_VERSION = VERSION = "2.12.3".freeze
103
- CODE_NAME = "Plutonian Photo Shoot".freeze
102
+ PUMA_VERSION = VERSION = "2.13.0".freeze
103
+ CODE_NAME = "A Midsummer Code's Dream".freeze
104
104
 
105
105
  FAST_TRACK_KA_TIMEOUT = 0.2
106
106
 
@@ -156,6 +156,19 @@ module Puma
156
156
  @options[:workers] = count.to_i
157
157
  end
158
158
 
159
+ # *Cluster mode only* Code to run immediately before master process
160
+ # forks workers (once on boot). These hooks can block if necessary
161
+ # to wait for background operations unknown to puma to finish before
162
+ # the process terminates.
163
+ # This can be used to close any connections to remote servers (database, redis, ...)
164
+ # that were opened when preloading the code
165
+ #
166
+ # This can be called multiple times to add hooks.
167
+ #
168
+ def before_fork(&block)
169
+ @options[:before_fork] << block
170
+ end
171
+
159
172
  # *Cluster mode only* Code to run immediately before a worker shuts
160
173
  # down (after it has finished processing HTTP requests). These hooks
161
174
  # can block if necessary to wait for background operations unknown
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.12.3
4
+ version: 2.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-04 00:00:00.000000000 Z
11
+ date: 2015-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc