puma 2.11.1 → 2.11.2

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: 4b495e74e45d4bc182f179febf4fa01f881fbf44
4
- data.tar.gz: 664e64737272b0befe90f6bbc4b4502116a8a31d
3
+ metadata.gz: 48c8ae38ddb47bb86ee31ba25019f04fb213a9b8
4
+ data.tar.gz: 8f79fa19e0b4ad06c87030fa6b8a0af7ca978834
5
5
  SHA512:
6
- metadata.gz: 6bad4f3bd1ab507047f9021b038ef81ecd6062f4eacf287e15f8a3d12bc7656de793eae2f96dbd0ee4e69ca052bd043a5ad1a67a4085f8290286557b977885f6
7
- data.tar.gz: 8eb7a622f1286d3f076f146ca0a2a1da38c0647836c8e23b27d4a8aafb221d2d365dceaf9cfe9bbab413e1d45ce38cdd8f98b7c7f36947a4ec8a406fb19b312b
6
+ metadata.gz: 2b4497fdf7dd5233d501666882b8896c75b3b2b095f76ea2ca7b809e123ba39536a2ddf6c2ecf4b9c4fbee2c1faf3acbfd9488b49bbfe524f68cd8185523211e
7
+ data.tar.gz: f8d976a6b89d03cd6ae561564e56f9d5a6fb5d13c233375186fe0423c875af398cb72aee4cb3b1437e18a0f006457cfda98964e841d74355da07b86bf5b1bbbb
@@ -1,3 +1,26 @@
1
+ === 2.11.2 / 2015-04-11
2
+
3
+ * 2 minor features:
4
+ * Add `on_worker_fork` hook, which allows to mimic Unicorn's behavior
5
+ * Add shutdown_debug config option
6
+
7
+ * 4 bug fixes:
8
+ * Fix the Config constants not being available in the DSL. Fixes #683
9
+ * Ignore multiple port declarations
10
+ * Proper 'Connection' header handling compatible with HTTP 1.[01] protocols
11
+ * Use "Puma" instead of "puma" to reporting to New Relic
12
+
13
+ * 1 doc fixes:
14
+ * Add Gitter badge.
15
+
16
+ * 6 PRs merged:
17
+ * Merge pull request #657 from schneems/schneems/puma-once-port
18
+ * Merge pull request #658 from Tomohiro/newrelic-dispatcher-default-update
19
+ * Merge pull request #662 from basecrm/connection-compatibility
20
+ * Merge pull request #664 from fxposter/on-worker-fork
21
+ * Merge pull request #667 from JuanitoFatas/doc/gemspec
22
+ * Merge pull request #672 from chulkilee/refactor
23
+
1
24
  === 2.11.1 / 2015-02-11
2
25
 
3
26
  * 2 bug fixes:
@@ -41,6 +41,7 @@ lib/puma/control_cli.rb
41
41
  lib/puma/daemon_ext.rb
42
42
  lib/puma/delegation.rb
43
43
  lib/puma/detect.rb
44
+ lib/puma/dsl.rb
44
45
  lib/puma/events.rb
45
46
  lib/puma/io_buffer.rb
46
47
  lib/puma/java_io_buffer.rb
@@ -15,6 +15,14 @@ require 'rack/commonlogger'
15
15
  require 'rack/utils'
16
16
 
17
17
  module Puma
18
+ class << self
19
+ # The CLI exports its Puma::Configuration object here to allow
20
+ # apps to pick it up. An app needs to use it conditionally though
21
+ # since it is not set if the app is launched via another
22
+ # mechanism than the CLI class.
23
+ attr_accessor :cli_config
24
+ end
25
+
18
26
  # Handles invoke a Puma::Server in a command line style.
19
27
  #
20
28
  class CLI
@@ -35,7 +43,7 @@ module Puma
35
43
 
36
44
  @config = nil
37
45
 
38
- ENV['NEWRELIC_DISPATCHER'] ||= "puma"
46
+ ENV['NEWRELIC_DISPATCHER'] ||= "Puma"
39
47
 
40
48
  setup_options
41
49
  generate_restart_data
@@ -69,9 +77,15 @@ module Puma
69
77
  end
70
78
 
71
79
  def debug(str)
72
- if @options[:debug]
73
- @events.log "- #{str}"
74
- end
80
+ @events.log "- #{str}" if @options[:debug]
81
+ end
82
+
83
+ def clustered?
84
+ @options[:workers] > 0
85
+ end
86
+
87
+ def prune_bundler?
88
+ @options[:prune_bundler] && clustered? && !@options[:preload_app]
75
89
  end
76
90
 
77
91
  def jruby?
@@ -82,12 +96,207 @@ module Puma
82
96
  RUBY_PLATFORM =~ /mswin32|ming32/
83
97
  end
84
98
 
85
- def unsupported(str, cond=true)
86
- return unless cond
87
- @events.error str
99
+ def env
100
+ @options[:environment] || ENV['RACK_ENV'] || 'development'
101
+ end
102
+
103
+ def write_state
104
+ write_pid
105
+
106
+ path = @options[:state]
107
+ return unless path
108
+
109
+ state = { 'pid' => Process.pid }
110
+ cfg = @config.dup
111
+
112
+ [
113
+ :logger,
114
+ :before_worker_shutdown, :before_worker_boot, :before_worker_fork,
115
+ :after_worker_boot,
116
+ :on_restart, :lowlevel_error_handler
117
+ ].each { |k| cfg.options.delete(k) }
118
+ state['config'] = cfg
119
+
120
+ require 'yaml'
121
+ File.open(path, 'w') { |f| f.write state.to_yaml }
122
+ end
123
+
124
+ # If configured, write the pid of the current process out
125
+ # to a file.
126
+ #
127
+ def write_pid
128
+ path = @options[:pidfile]
129
+ return unless path
130
+
131
+ File.open(path, 'w') { |f| f.puts Process.pid }
132
+ cur = Process.pid
133
+ at_exit do
134
+ delete_pidfile if cur == Process.pid
135
+ end
136
+ end
137
+
138
+ def delete_pidfile
139
+ path = @options[:pidfile]
140
+ File.unlink(path) if path && File.exist?(path)
141
+ end
142
+
143
+ def graceful_stop
144
+ @runner.stop_blocked
145
+ log "=== puma shutdown: #{Time.now} ==="
146
+ log "- Goodbye!"
147
+ end
148
+
149
+ def jruby_daemon_start
150
+ require 'puma/jruby_restart'
151
+ JRubyRestart.daemon_start(@restart_dir, restart_args)
152
+ end
153
+
154
+ def restart!
155
+ @options[:on_restart].each do |block|
156
+ block.call self
157
+ end
158
+
159
+ if jruby?
160
+ close_binder_listeners
161
+
162
+ require 'puma/jruby_restart'
163
+ JRubyRestart.chdir_exec(@restart_dir, restart_args)
164
+ elsif windows?
165
+ close_binder_listeners
166
+
167
+ argv = restart_args
168
+ Dir.chdir(@restart_dir)
169
+ argv += [redirects] if RUBY_VERSION >= '1.9'
170
+ Kernel.exec(*argv)
171
+ else
172
+ redirects = {:close_others => true}
173
+ @binder.listeners.each_with_index do |(l, io), i|
174
+ ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
175
+ redirects[io.to_i] = io.to_i
176
+ end
177
+
178
+ argv = restart_args
179
+ Dir.chdir(@restart_dir)
180
+ argv += [redirects] if RUBY_VERSION >= '1.9'
181
+ Kernel.exec(*argv)
182
+ end
183
+ end
184
+
185
+ # Parse the options, load the rackup, start the server and wait
186
+ # for it to finish.
187
+ #
188
+ def run
189
+ begin
190
+ parse_options
191
+ rescue UnsupportedOption
192
+ exit 1
193
+ end
194
+
195
+ dir = @options[:directory]
196
+ Dir.chdir(dir) if dir
197
+
198
+ prune_bundler if prune_bundler?
199
+
200
+ set_rack_environment
201
+
202
+ if clustered?
203
+ @events.formatter = Events::PidFormatter.new
204
+ @options[:logger] = @events
205
+
206
+ @runner = Cluster.new(self)
207
+ else
208
+ @runner = Single.new(self)
209
+ end
210
+
211
+ setup_signals
212
+ set_process_title
213
+
214
+ @status = :run
215
+
216
+ @runner.run
217
+
218
+ case @status
219
+ when :halt
220
+ log "* Stopping immediately!"
221
+ when :run, :stop
222
+ graceful_stop
223
+ when :restart
224
+ log "* Restarting..."
225
+ @runner.before_restart
226
+ restart!
227
+ when :exit
228
+ # nothing
229
+ end
230
+ end
231
+
232
+ def stop
233
+ @status = :stop
234
+ @runner.stop
235
+ end
236
+
237
+ def restart
238
+ @status = :restart
239
+ @runner.restart
240
+ end
241
+
242
+ def reload_worker_directory
243
+ @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
244
+ end
245
+
246
+ def phased_restart
247
+ unless @runner.respond_to?(:phased_restart) and @runner.phased_restart
248
+ log "* phased-restart called but not available, restarting normally."
249
+ return restart
250
+ end
251
+ true
252
+ end
253
+
254
+ def redirect_io
255
+ @runner.redirect_io
256
+ end
257
+
258
+ def stats
259
+ @runner.stats
260
+ end
261
+
262
+ def halt
263
+ @status = :halt
264
+ @runner.halt
265
+ end
266
+
267
+ private
268
+ def title
269
+ buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
270
+ buffer << " [#{@options[:tag]}]" if @options[:tag]
271
+ buffer
272
+ end
273
+
274
+ def unsupported(str)
275
+ @events.error(str)
88
276
  raise UnsupportedOption
89
277
  end
90
278
 
279
+ def restart_args
280
+ cmd = @options[:restart_cmd]
281
+ if cmd
282
+ cmd.split(' ') + @original_argv
283
+ else
284
+ @restart_argv
285
+ end
286
+ end
287
+
288
+ def set_process_title
289
+ Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
290
+ end
291
+
292
+ def find_config
293
+ if @options[:config_file] == '-'
294
+ @options[:config_file] = nil
295
+ else
296
+ @options[:config_file] ||= %W(config/puma/#{env}.rb config/puma.rb).find { |f| File.exist?(f) }
297
+ end
298
+ end
299
+
91
300
  # Build the OptionParser object to handle the available options.
92
301
  #
93
302
  def setup_options
@@ -101,6 +310,7 @@ module Puma
101
310
  :daemon => false,
102
311
  :before_worker_shutdown => [],
103
312
  :before_worker_boot => [],
313
+ :before_worker_fork => [],
104
314
  :after_worker_boot => []
105
315
  }
106
316
 
@@ -209,124 +419,16 @@ module Puma
209
419
  o.on "--tag NAME", "Additional text to display in process listing" do |arg|
210
420
  @options[:tag] = arg
211
421
  end
212
- end
213
-
214
- @parser.banner = "puma <options> <rackup file>"
215
-
216
- @parser.on_tail "-h", "--help", "Show help" do
217
- log @parser
218
- exit 1
219
- end
220
- end
221
-
222
- def write_state
223
- write_pid
224
-
225
- require 'yaml'
226
-
227
- if path = @options[:state]
228
- state = { "pid" => Process.pid }
229
-
230
- cfg = @config.dup
231
-
232
- [ :logger, :before_worker_shutdown, :before_worker_boot, :after_worker_boot, :on_restart, :lowlevel_error_handler ].each { |o| cfg.options.delete o }
233
-
234
- state["config"] = cfg
235
-
236
- File.open(path, "w") do |f|
237
- f.write state.to_yaml
238
- end
239
- end
240
- end
241
-
242
- # If configured, write the pid of the current process out
243
- # to a file.
244
- #
245
- def write_pid
246
- if path = @options[:pidfile]
247
- File.open(path, "w") do |f|
248
- f.puts Process.pid
249
- end
250
422
 
251
- cur = Process.pid
423
+ o.banner = "puma <options> <rackup file>"
252
424
 
253
- at_exit do
254
- if cur == Process.pid
255
- delete_pidfile
256
- end
257
- end
258
- end
259
- end
260
-
261
- def env
262
- # Try the user option first, then the environment variable,
263
- # finally default to development
264
- @options[:environment] || ENV['RACK_ENV'] || 'development'
265
- end
266
-
267
- def set_rack_environment
268
- @options[:environment] = env
269
- ENV['RACK_ENV'] = env
270
- end
271
-
272
- def delete_pidfile
273
- if path = @options[:pidfile]
274
- File.unlink path if File.exist? path
275
- end
276
- end
277
-
278
- def find_config
279
- if cfg = @options[:config_file]
280
- # Allow - to disable config finding
281
- if cfg == "-"
282
- @options[:config_file] = nil
283
- return
425
+ o.on_tail "-h", "--help", "Show help" do
426
+ log o
427
+ exit 1
284
428
  end
285
-
286
- return
287
- end
288
-
289
- pos = ["config/puma/#{env}.rb", "config/puma.rb"]
290
- @options[:config_file] = pos.find { |f| File.exist? f }
291
- end
292
-
293
- # :nodoc:
294
- def parse_options
295
- @parser.parse! @argv
296
-
297
- if @argv.last
298
- @options[:rackup] = @argv.shift
299
- end
300
-
301
- find_config
302
-
303
- @config = Puma::Configuration.new @options
304
-
305
- # Advertise the Configuration
306
- Puma.cli_config = @config
307
-
308
- @config.load
309
-
310
- if clustered?
311
- unsupported "worker mode not supported on JRuby or Windows",
312
- jruby? || windows?
313
- end
314
-
315
- if @options[:daemon] and windows?
316
- unsupported "daemon mode not supported on Windows"
317
429
  end
318
430
  end
319
431
 
320
- def clustered?
321
- @options[:workers] > 0
322
- end
323
-
324
- def graceful_stop
325
- @runner.stop_blocked
326
- log "=== puma shutdown: #{Time.now} ==="
327
- log "- Goodbye!"
328
- end
329
-
330
432
  def generate_restart_data
331
433
  # Use the same trick as unicorn, namely favor PWD because
332
434
  # it will contain an unresolved symlink, useful for when
@@ -372,157 +474,9 @@ module Puma
372
474
  end
373
475
  end
374
476
 
375
- def restart_args
376
- if cmd = @options[:restart_cmd]
377
- cmd.split(' ') + @original_argv
378
- else
379
- @restart_argv
380
- end
381
- end
382
-
383
- def jruby_daemon_start
384
- require 'puma/jruby_restart'
385
- JRubyRestart.daemon_start(@restart_dir, restart_args)
386
- end
387
-
388
- def restart!
389
- @options[:on_restart].each do |block|
390
- block.call self
391
- end
392
-
393
- if jruby?
394
- @binder.listeners.each_with_index do |(str,io),i|
395
- io.close
396
-
397
- # We have to unlink a unix socket path that's not being used
398
- uri = URI.parse str
399
- if uri.scheme == "unix"
400
- path = "#{uri.host}#{uri.path}"
401
- File.unlink path
402
- end
403
- end
404
-
405
- require 'puma/jruby_restart'
406
- JRubyRestart.chdir_exec(@restart_dir, restart_args)
407
-
408
- elsif windows?
409
- @binder.listeners.each_with_index do |(str,io),i|
410
- io.close
411
-
412
- # We have to unlink a unix socket path that's not being used
413
- uri = URI.parse str
414
- if uri.scheme == "unix"
415
- path = "#{uri.host}#{uri.path}"
416
- File.unlink path
417
- end
418
- end
419
-
420
- argv = restart_args
421
-
422
- Dir.chdir @restart_dir
423
-
424
- argv += [redirects] unless RUBY_VERSION < '1.9'
425
- Kernel.exec(*argv)
426
-
427
- else
428
- redirects = {:close_others => true}
429
- @binder.listeners.each_with_index do |(l,io),i|
430
- ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
431
- redirects[io.to_i] = io.to_i
432
- end
433
-
434
- argv = restart_args
435
-
436
- Dir.chdir @restart_dir
437
-
438
- argv += [redirects] unless RUBY_VERSION < '1.9'
439
-
440
- Kernel.exec(*argv)
441
- end
442
- end
443
-
444
- def prune_bundler?
445
- @options[:prune_bundler] && clustered? && !@options[:preload_app]
446
- end
447
-
448
- # Parse the options, load the rackup, start the server and wait
449
- # for it to finish.
450
- #
451
- def run
452
- begin
453
- parse_options
454
- rescue UnsupportedOption
455
- exit 1
456
- end
457
-
458
- if dir = @options[:directory]
459
- Dir.chdir dir
460
- end
461
-
462
- if prune_bundler? && defined?(Bundler)
463
- puma = Bundler.rubygems.loaded_specs("puma")
464
-
465
- dirs = puma.require_paths.map { |x| File.join(puma.full_gem_path, x) }
466
-
467
- puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, "../bin/puma-wild") }
468
-
469
- deps = puma.runtime_dependencies.map { |d|
470
- spec = Bundler.rubygems.loaded_specs(d.name)
471
- "#{d.name}:#{spec.version.to_s}"
472
- }.join(",")
473
-
474
- if puma_lib_dir
475
- log "* Pruning Bundler environment"
476
-
477
- home = ENV['GEM_HOME']
478
-
479
- Bundler.with_clean_env do
480
-
481
- ENV['GEM_HOME'] = home
482
-
483
- wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
484
-
485
- wild_loadpath = dirs.join(":")
486
-
487
- args = [Gem.ruby] + [wild, "-I", wild_loadpath, deps] + @original_argv
488
-
489
- Kernel.exec(*args)
490
- end
491
- end
492
-
493
- log "! Unable to prune Bundler environment, continuing"
494
- end
495
-
496
- set_rack_environment
497
-
498
- if clustered?
499
- @events.formatter = Events::PidFormatter.new
500
- @options[:logger] = @events
501
-
502
- @runner = Cluster.new(self)
503
- else
504
- @runner = Single.new(self)
505
- end
506
-
507
- setup_signals
508
- set_process_title
509
-
510
- @status = :run
511
-
512
- @runner.run
513
-
514
- case @status
515
- when :halt
516
- log "* Stopping immediately!"
517
- when :run, :stop
518
- graceful_stop
519
- when :restart
520
- log "* Restarting..."
521
- @runner.before_restart
522
- restart!
523
- when :exit
524
- # nothing
525
- end
477
+ def set_rack_environment
478
+ @options[:environment] = env
479
+ ENV['RACK_ENV'] = env
526
480
  end
527
481
 
528
482
  def setup_signals
@@ -567,50 +521,62 @@ module Puma
567
521
  end
568
522
  end
569
523
 
570
- def stop
571
- @status = :stop
572
- @runner.stop
524
+ def close_binder_listeners
525
+ @binder.listeners.each do |l, io|
526
+ io.close
527
+ uri = URI.parse(l)
528
+ next unless uri.scheme == 'unix'
529
+ File.unlink("#{uri.host}#{uri.path}")
530
+ end
573
531
  end
574
532
 
575
- def restart
576
- @status = :restart
577
- @runner.restart
578
- end
533
+ def parse_options
534
+ @parser.parse! @argv
579
535
 
580
- def reload_worker_directory
581
- @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
582
- end
536
+ @options[:rackup] = @argv.shift if @argv.last
583
537
 
584
- def phased_restart
585
- unless @runner.respond_to?(:phased_restart) and @runner.phased_restart
586
- log "* phased-restart called but not available, restarting normally."
587
- return restart
538
+ find_config
539
+
540
+ @config = Puma::Configuration.new @options
541
+
542
+ # Advertise the Configuration
543
+ Puma.cli_config = @config
544
+
545
+ @config.load
546
+
547
+ if clustered? && (jruby? || windows?)
548
+ unsupported 'worker mode not supported on JRuby or Windows'
588
549
  end
589
- true
590
- end
591
550
 
592
- def redirect_io
593
- @runner.redirect_io
551
+ if @options[:daemon] && windows?
552
+ unsupported 'daemon mode not supported on Windows'
553
+ end
594
554
  end
595
555
 
596
- def stats
597
- @runner.stats
598
- end
556
+ def prune_bundler
557
+ return unless defined?(Bundler)
558
+ puma = Bundler.rubygems.loaded_specs("puma")
559
+ dirs = puma.require_paths.map { |x| File.join(puma.full_gem_path, x) }
560
+ puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
599
561
 
600
- def halt
601
- @status = :halt
602
- @runner.halt
603
- end
562
+ unless puma_lib_dir
563
+ log "! Unable to prune Bundler environment, continuing"
564
+ return
565
+ end
604
566
 
605
- private
606
- def title
607
- buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
608
- buffer << " [#{@options[:tag]}]" if @options[:tag]
609
- buffer
610
- end
567
+ deps = puma.runtime_dependencies.map do |d|
568
+ spec = Bundler.rubygems.loaded_specs(d.name)
569
+ "#{d.name}:#{spec.version.to_s}"
570
+ end
611
571
 
612
- def set_process_title
613
- Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
572
+ log '* Pruning Bundler environment'
573
+ home = ENV['GEM_HOME']
574
+ Bundler.with_clean_env do
575
+ ENV['GEM_HOME'] = home
576
+ wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
577
+ args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
578
+ Kernel.exec(*args)
579
+ end
614
580
  end
615
581
  end
616
582
  end