puma 2.0.0.b4 → 2.0.0.b5

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.

@@ -1,3 +1,20 @@
1
+ === 2.0.0.b5 / 2013-02-05
2
+
3
+ * 2 major features:
4
+ * Add phased worker upgrade
5
+ * Add support for the rack hijack protocol
6
+
7
+ * 2 minor features:
8
+ * Add -R to specify the restart command
9
+ * Add config file option to specify the restart command
10
+
11
+ * 5 bug fixes:
12
+ * Cleanup pipes properly. Fixes #182
13
+ * Daemonize earlier so that we don't lose app threads. Fixes #183
14
+ * Drain the notification pipe. Fixes #176, thanks @cryo28
15
+ * Move write_pid to after we daemonize. Fixes #180
16
+ * Redirect IO properly and emit message for checkpointing
17
+
1
18
  === 2.0.0.b4 / 2012-12-12
2
19
 
3
20
  * 4 bug fixes:
@@ -48,6 +48,7 @@ lib/puma/rack_patch.rb
48
48
  lib/puma/reactor.rb
49
49
  lib/puma/server.rb
50
50
  lib/puma/thread_pool.rb
51
+ lib/puma/util.rb
51
52
  lib/rack/handler/puma.rb
52
53
  puma.gemspec
53
54
  tools/jungle/README.md
data/Rakefile CHANGED
@@ -19,7 +19,7 @@ HOE = Hoe.spec "puma" do
19
19
 
20
20
  require_ruby_version ">= 1.8.7"
21
21
 
22
- dependency "rack", "~> 1.2"
22
+ dependency "rack", [">= 1.1", "< 2.0"]
23
23
 
24
24
  extra_dev_deps << ["rake-compiler", "~> 0.8.0"]
25
25
  end
@@ -7,6 +7,7 @@ require 'puma/configuration'
7
7
  require 'puma/binder'
8
8
  require 'puma/detect'
9
9
  require 'puma/daemon_ext'
10
+ require 'puma/util'
10
11
 
11
12
  require 'rack/commonlogger'
12
13
  require 'rack/utils'
@@ -27,6 +28,7 @@ module Puma
27
28
  @stdout = stdout
28
29
  @stderr = stderr
29
30
 
31
+ @phase = 0
30
32
  @workers = []
31
33
 
32
34
  @events = Events.new @stdout, @stderr
@@ -35,6 +37,7 @@ module Puma
35
37
  @status = nil
36
38
 
37
39
  @restart = false
40
+ @phased_state = :idle
38
41
 
39
42
  ENV['NEWRELIC_DISPATCHER'] ||= "puma"
40
43
 
@@ -82,6 +85,10 @@ module Puma
82
85
  arg0 = [Gem.ruby, "-S", $0]
83
86
  end
84
87
 
88
+ # Detect and reinject -Ilib from the command line
89
+ lib = File.expand_path "lib"
90
+ arg0[1,0] = ["-I", lib] if $:[0] == lib
91
+
85
92
  @restart_argv = arg0 + ARGV
86
93
  end
87
94
  end
@@ -225,7 +232,7 @@ module Puma
225
232
  @options[:quiet] = true
226
233
  end
227
234
 
228
- o.on "--restart-cmd CMD",
235
+ o.on "-R", "--restart-cmd CMD",
229
236
  "The puma command to run during a hot restart",
230
237
  "Default: inferred" do |cmd|
231
238
  @options[:restart_cmd] = cmd
@@ -291,6 +298,8 @@ module Puma
291
298
  end
292
299
 
293
300
  def write_state
301
+ write_pid
302
+
294
303
  require 'yaml'
295
304
 
296
305
  if path = @options[:state]
@@ -334,10 +343,12 @@ module Puma
334
343
 
335
344
  if stdout
336
345
  STDOUT.reopen stdout, (append ? "a" : "w")
346
+ STDOUT.puts "=== puma startup: #{Time.now} ==="
337
347
  end
338
348
 
339
349
  if stderr
340
- STDOUT.reopen stderr, (append ? "a" : "w")
350
+ STDERR.reopen stderr, (append ? "a" : "w")
351
+ STDERR.puts "=== puma startup: #{Time.now} ==="
341
352
  end
342
353
  end
343
354
 
@@ -364,9 +375,6 @@ module Puma
364
375
 
365
376
  set_rack_environment
366
377
 
367
- write_pid
368
- write_state
369
-
370
378
  if clustered
371
379
  run_cluster
372
380
  else
@@ -375,6 +383,8 @@ module Puma
375
383
  end
376
384
 
377
385
  def run_single
386
+ write_state
387
+
378
388
  min_t = @options[:min_threads]
379
389
  max_t = @options[:max_threads]
380
390
 
@@ -384,6 +394,10 @@ module Puma
384
394
 
385
395
  @binder.parse @options[:binds], self
386
396
 
397
+ if @options[:daemon]
398
+ Process.daemon(true, true)
399
+ end
400
+
387
401
  server = Puma::Server.new @config.app, @events
388
402
  server.binder = @binder
389
403
  server.min_threads = min_t
@@ -441,9 +455,7 @@ module Puma
441
455
  log "*** Sorry signal SIGTERM not implemented, gracefully stopping feature disabled!"
442
456
  end
443
457
 
444
- if @options[:daemon]
445
- Process.daemon(true)
446
- else
458
+ unless @options[:daemon]
447
459
  log "Use Ctrl-C to stop"
448
460
  end
449
461
 
@@ -473,6 +485,7 @@ module Puma
473
485
  $0 = "puma: cluster worker: #{@master_pid}"
474
486
  Signal.trap "SIGINT", "IGNORE"
475
487
 
488
+ @master_read.close
476
489
  @suicide_pipe.close
477
490
 
478
491
  Thread.new do
@@ -493,7 +506,12 @@ module Puma
493
506
  server.stop
494
507
  end
495
508
 
509
+ @worker_write << "b#{Process.pid}\n"
510
+
496
511
  server.run.join
512
+
513
+ ensure
514
+ @worker_write.close
497
515
  end
498
516
 
499
517
  def stop_workers
@@ -509,12 +527,27 @@ module Puma
509
527
  end
510
528
  end
511
529
 
530
+ def start_phased_restart
531
+ @phase += 1
532
+ log "- Starting phased worker restart, phase: #{@phase}"
533
+ end
534
+
512
535
  class Worker
513
- def initialize(pid)
536
+ def initialize(pid, phase)
514
537
  @pid = pid
538
+ @phase = phase
539
+ @stage = :started
515
540
  end
516
541
 
517
- attr_reader :pid
542
+ attr_reader :pid, :phase
543
+
544
+ def booted?
545
+ @stage == :booted
546
+ end
547
+
548
+ def boot!
549
+ @stage = :booted
550
+ end
518
551
 
519
552
  def term
520
553
  begin
@@ -530,8 +563,16 @@ module Puma
530
563
  diff.times do
531
564
  pid = fork { worker }
532
565
  debug "Spawned worker: #{pid}"
533
- @workers << Worker.new(pid)
566
+ @workers << Worker.new(pid, @phase)
534
567
  end
568
+
569
+ if diff > 0
570
+ @phased_state = :idle
571
+ end
572
+ end
573
+
574
+ def all_workers_booted?
575
+ @workers.count { |w| !w.booted? } == 0
535
576
  end
536
577
 
537
578
  def check_workers
@@ -543,6 +584,20 @@ module Puma
543
584
  end
544
585
 
545
586
  spawn_workers
587
+
588
+ if @phased_state == :idle && all_workers_booted?
589
+ # If we're running at proper capacity, check to see if
590
+ # we need to phase any workers out (which will restart
591
+ # in the right phase).
592
+ #
593
+ w = @workers.find { |x| x.phase != @phase }
594
+
595
+ if w
596
+ @phased_state = :waiting
597
+ log "- Stopping #{w.pid} for phased upgrade..."
598
+ w.term
599
+ end
600
+ end
546
601
  end
547
602
 
548
603
  def run_cluster
@@ -555,7 +610,7 @@ module Puma
555
610
 
556
611
  @master_pid = Process.pid
557
612
 
558
- read, write = IO.pipe
613
+ read, write = Puma::Util.pipe
559
614
 
560
615
  Signal.trap "SIGCHLD" do
561
616
  write.write "!"
@@ -580,21 +635,34 @@ module Puma
580
635
  rescue Exception
581
636
  end
582
637
 
638
+ phased_restart = false
639
+
640
+ begin
641
+ Signal.trap "SIGUSR1" do
642
+ phased_restart = true
643
+ write.write "!"
644
+ end
645
+ rescue Exception
646
+ end
647
+
583
648
  # Used by the workers to detect if the master process dies.
584
649
  # If select says that @check_pipe is ready, it's because the
585
650
  # master has exited and @suicide_pipe has been automatically
586
651
  # closed.
587
652
  #
588
- @check_pipe, @suicide_pipe = IO.pipe
653
+ @check_pipe, @suicide_pipe = Puma::Util.pipe
589
654
 
590
655
  if @options[:daemon]
591
- Process.daemon(true)
656
+ Process.daemon(true, true)
592
657
  else
593
658
  log "Use Ctrl-C to stop"
594
659
  end
595
660
 
596
661
  redirect_io
597
662
 
663
+ write_state
664
+
665
+ @master_read, @worker_write = read, write
598
666
  spawn_workers
599
667
 
600
668
  Signal.trap "SIGINT" do
@@ -605,8 +673,30 @@ module Puma
605
673
  begin
606
674
  while !stop
607
675
  begin
608
- IO.select([read], nil, nil, 5)
676
+ res = IO.select([read], nil, nil, 5)
677
+
678
+ if res
679
+ req = read.read_nonblock(1)
680
+
681
+ if req == "b"
682
+ pid = read.gets.to_i
683
+ w = @workers.find { |w| w.pid == pid }
684
+ if w
685
+ w.boot!
686
+ log "- Worker #{pid} booted, phase: #{w.phase}"
687
+ else
688
+ log "! Out-of-sync worker list, no #{pid} worker"
689
+ end
690
+ end
691
+ end
692
+
609
693
  check_workers
694
+
695
+ if phased_restart
696
+ start_phased_restart
697
+ phased_restart = false
698
+ end
699
+
610
700
  rescue Interrupt
611
701
  stop = true
612
702
  end
@@ -615,6 +705,10 @@ module Puma
615
705
  stop_workers
616
706
  ensure
617
707
  delete_pidfile
708
+ @check_pipe.close
709
+ @suicide_pipe.close
710
+ read.close
711
+ write.close
618
712
  end
619
713
 
620
714
  if @restart
@@ -36,14 +36,22 @@ module Puma
36
36
  @timeout_at = nil
37
37
 
38
38
  @requests_served = 0
39
+ @hijacked = false
39
40
  end
40
41
 
41
- attr_reader :env, :to_io, :body, :io, :timeout_at, :ready
42
+ attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked
42
43
 
43
44
  def inspect
44
45
  "#<Puma::Client:0x#{object_id.to_s(16)} @ready=#{@ready.inspect}>"
45
46
  end
46
47
 
48
+ # For the hijack protocol (allows us to just put the Client object
49
+ # into the env)
50
+ def call
51
+ @hijacked = true
52
+ env[HIJACK_IO] ||= @io
53
+ end
54
+
47
55
  def set_timeout(val)
48
56
  @timeout_at = Time.now + val
49
57
  end
@@ -176,6 +176,14 @@ module Puma
176
176
  @options[:on_restart] << blk
177
177
  end
178
178
 
179
+ # Command to use to restart puma. This should be just how to
180
+ # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
181
+ # to puma, as those are the same as the original process.
182
+ #
183
+ def restart_command(cmd)
184
+ @options[:request_cmd] = cmd
185
+ end
186
+
179
187
  # Store the pid of the server in the file at +path+.
180
188
  def pidfile(path)
181
189
  @options[:pidfile] = path
@@ -28,7 +28,7 @@ module Puma
28
28
  # too taxing on performance.
29
29
  module Const
30
30
 
31
- PUMA_VERSION = VERSION = "2.0.0.b4".freeze
31
+ PUMA_VERSION = VERSION = "2.0.0.b5".freeze
32
32
 
33
33
  FAST_TRACK_KA_TIMEOUT = 0.2
34
34
 
@@ -147,5 +147,9 @@ module Puma
147
147
  COLON = ": ".freeze
148
148
 
149
149
  NEWLINE = "\n".freeze
150
+
151
+ HIJACK_P = "rack.hijack?".freeze
152
+ HIJACK = "rack.hijack".freeze
153
+ HIJACK_IO = "rack.hijack_io".freeze
150
154
  end
151
155
  end
@@ -1,3 +1,5 @@
1
+ require 'puma/util'
2
+
1
3
  module Puma
2
4
  class Reactor
3
5
  DefaultSleepFor = 5
@@ -8,7 +10,7 @@ module Puma
8
10
  @app_pool = app_pool
9
11
 
10
12
  @mutex = Mutex.new
11
- @ready, @trigger = IO.pipe
13
+ @ready, @trigger = Puma::Util.pipe
12
14
  @input = []
13
15
  @sleep_for = DefaultSleepFor
14
16
  @timeouts = []
@@ -89,6 +91,9 @@ module Puma
89
91
  calculate_sleep
90
92
  end
91
93
  end
94
+ ensure
95
+ @trigger.close
96
+ @ready.close
92
97
  end
93
98
 
94
99
  def run_in_thread
@@ -135,11 +140,18 @@ module Puma
135
140
 
136
141
  # Close all watched sockets and clear them from being watched
137
142
  def clear!
138
- @trigger << "c"
143
+ begin
144
+ @trigger << "c"
145
+ rescue IOError
146
+ end
139
147
  end
140
148
 
141
149
  def shutdown
142
- @trigger << "!"
150
+ begin
151
+ @trigger << "!"
152
+ rescue IOError
153
+ end
154
+
143
155
  @thread.join
144
156
  end
145
157
  end
@@ -11,6 +11,7 @@ require 'puma/client'
11
11
  require 'puma/binder'
12
12
  require 'puma/delegation'
13
13
  require 'puma/accept_nonblock'
14
+ require 'puma/util'
14
15
 
15
16
  require 'puma/puma_http11'
16
17
 
@@ -49,7 +50,7 @@ module Puma
49
50
  @app = app
50
51
  @events = events
51
52
 
52
- @check, @notify = IO.pipe
53
+ @check, @notify = Puma::Util.pipe
53
54
 
54
55
  @status = :stop
55
56
 
@@ -61,7 +62,6 @@ module Puma
61
62
  @thread_pool = nil
62
63
 
63
64
  @persistent_timeout = PERSISTENT_TIMEOUT
64
- @persistent_check, @persistent_wakeup = IO.pipe
65
65
 
66
66
  @binder = Binder.new(events)
67
67
  @first_data_timeout = FIRST_DATA_TIMEOUT
@@ -191,8 +191,10 @@ module Puma
191
191
 
192
192
  @reactor.shutdown
193
193
  ensure
194
+ @check.close
195
+ @notify.close
196
+
194
197
  unless @status == :restart
195
- @check.close
196
198
  @binder.close
197
199
  end
198
200
  end
@@ -330,6 +332,9 @@ module Puma
330
332
 
331
333
  env[PUMA_SOCKET] = client
332
334
 
335
+ env[HIJACK_P] = true
336
+ env[HIJACK] = req
337
+
333
338
  body = req.body
334
339
 
335
340
  env[RACK_INPUT] = body
@@ -343,6 +348,9 @@ module Puma
343
348
  begin
344
349
  begin
345
350
  status, headers, res_body = @app.call(env)
351
+
352
+ return :async if req.hijacked
353
+
346
354
  status = status.to_i
347
355
 
348
356
  if status == -1
@@ -404,6 +412,8 @@ module Puma
404
412
  end
405
413
  end
406
414
 
415
+ response_hijack = nil
416
+
407
417
  headers.each do |k, vs|
408
418
  case k
409
419
  when CONTENT_LENGTH2
@@ -414,6 +424,9 @@ module Puma
414
424
  content_length = nil
415
425
  when CONTENT_TYPE
416
426
  next if no_body
427
+ when HIJACK
428
+ response_hijack = vs
429
+ next
417
430
  end
418
431
 
419
432
  vs.split(NEWLINE).each do |v|
@@ -433,18 +446,25 @@ module Puma
433
446
  lines << CONNECTION_CLOSE
434
447
  end
435
448
 
436
- if content_length
437
- lines.append CONTENT_LENGTH_S, content_length.to_s, line_ending
438
- chunked = false
439
- elsif allow_chunked
440
- lines << TRANSFER_ENCODING_CHUNKED
441
- chunked = true
449
+ unless response_hijack
450
+ if content_length
451
+ lines.append CONTENT_LENGTH_S, content_length.to_s, line_ending
452
+ chunked = false
453
+ elsif allow_chunked
454
+ lines << TRANSFER_ENCODING_CHUNKED
455
+ chunked = true
456
+ end
442
457
  end
443
458
 
444
459
  lines << line_ending
445
460
 
446
461
  fast_write client, lines.to_s
447
462
 
463
+ if response_hijack
464
+ response_hijack.call client
465
+ return :async
466
+ end
467
+
448
468
  res_body.each do |part|
449
469
  if chunked
450
470
  client.syswrite part.bytesize.to_s(16)
@@ -545,21 +565,18 @@ module Puma
545
565
  # off the request queue before finally exiting.
546
566
  #
547
567
  def stop(sync=false)
548
- @persistent_wakeup.close
549
568
  @notify << STOP_COMMAND
550
569
 
551
570
  @thread.join if @thread && sync
552
571
  end
553
572
 
554
573
  def halt(sync=false)
555
- @persistent_wakeup.close
556
574
  @notify << HALT_COMMAND
557
575
 
558
576
  @thread.join if @thread && sync
559
577
  end
560
578
 
561
579
  def begin_restart
562
- @persistent_wakeup.close
563
580
  @notify << RESTART_COMMAND
564
581
  end
565
582
 
@@ -0,0 +1,9 @@
1
+ module Puma
2
+ module Util
3
+ module_function
4
+
5
+ def pipe
6
+ IO.pipe
7
+ end
8
+ end
9
+ end
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "puma"
5
- s.version = "2.0.0.b4"
5
+ s.version = "2.0.0.b5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Evan Phoenix"]
9
- s.date = "2012-12-13"
9
+ s.date = "2013-02-06"
10
10
  s.description = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications. It can be used with any application that supports Rack, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for [Rubinius](http://rubini.us), but also works well with JRuby and MRI. Puma is intended for use in both development and production environments.\n\nUnder the hood, Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request in a thread from an internal thread pool (which you can control). This allows Puma to provide real concurrency for your web application!\n\nWith Rubinius 2.0, Puma will utilize all cores on your CPU with real threads, meaning you won't have to spawn multiple processes to increase throughput. You can expect to see a similar benefit from JRuby.\n\nOn MRI, there is a Global Interpreter Lock (GIL) that ensures only one thread can be run at a time. But if you're doing a lot of blocking IO (such as HTTP calls to external APIs like Twitter), Puma still improves MRI's throughput by allowing blocking IO to be run concurrently (EventMachine-based servers such as Thin turn off this ability, requiring you to use special libraries). Your mileage may vary. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like [Rubinius](http://rubini.us) or [JRuby](http://jruby.org)."
11
11
  s.email = ["evan@phx.io"]
12
12
  s.executables = ["puma", "pumactl"]
13
13
  s.extensions = ["ext/puma_http11/extconf.rb"]
14
14
  s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
15
- s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "docs/config.md", "docs/nginx.md", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/io_buffer.c", "ext/puma_http11/mini_ssl.c", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/org/jruby/puma/MiniSSL.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/accept_nonblock.rb", "lib/puma/app/status.rb", "lib/puma/binder.rb", "lib/puma/capistrano.rb", "lib/puma/cli.rb", "lib/puma/client.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/daemon_ext.rb", "lib/puma/delegation.rb", "lib/puma/detect.rb", "lib/puma/events.rb", "lib/puma/io_buffer.rb", "lib/puma/java_io_buffer.rb", "lib/puma/jruby_restart.rb", "lib/puma/minissl.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "tools/jungle/README.md", "tools/jungle/puma", "tools/jungle/run-puma", "test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_minissl.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
15
+ s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "docs/config.md", "docs/nginx.md", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/io_buffer.c", "ext/puma_http11/mini_ssl.c", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/org/jruby/puma/MiniSSL.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/accept_nonblock.rb", "lib/puma/app/status.rb", "lib/puma/binder.rb", "lib/puma/capistrano.rb", "lib/puma/cli.rb", "lib/puma/client.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/daemon_ext.rb", "lib/puma/delegation.rb", "lib/puma/detect.rb", "lib/puma/events.rb", "lib/puma/io_buffer.rb", "lib/puma/java_io_buffer.rb", "lib/puma/jruby_restart.rb", "lib/puma/minissl.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/puma/util.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "tools/jungle/README.md", "tools/jungle/puma", "tools/jungle/run-puma", "test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_minissl.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
16
16
  s.homepage = "http://puma.io"
17
17
  s.rdoc_options = ["--main", "README.md"]
18
18
  s.require_paths = ["lib"]
19
19
  s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
20
20
  s.rubyforge_project = "puma"
21
- s.rubygems_version = "1.8.24"
21
+ s.rubygems_version = "1.8.25"
22
22
  s.summary = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications"
23
23
  s.test_files = ["test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_minissl.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
24
24
 
@@ -26,18 +26,18 @@ Gem::Specification.new do |s|
26
26
  s.specification_version = 3
27
27
 
28
28
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
- s.add_runtime_dependency(%q<rack>, ["~> 1.2"])
29
+ s.add_runtime_dependency(%q<rack>, ["< 2.0", ">= 1.1"])
30
30
  s.add_development_dependency(%q<rdoc>, ["~> 3.10"])
31
31
  s.add_development_dependency(%q<rake-compiler>, ["~> 0.8.0"])
32
32
  s.add_development_dependency(%q<hoe>, ["~> 3.0"])
33
33
  else
34
- s.add_dependency(%q<rack>, ["~> 1.2"])
34
+ s.add_dependency(%q<rack>, ["< 2.0", ">= 1.1"])
35
35
  s.add_dependency(%q<rdoc>, ["~> 3.10"])
36
36
  s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
37
37
  s.add_dependency(%q<hoe>, ["~> 3.0"])
38
38
  end
39
39
  else
40
- s.add_dependency(%q<rack>, ["~> 1.2"])
40
+ s.add_dependency(%q<rack>, ["< 2.0", ">= 1.1"])
41
41
  s.add_dependency(%q<rdoc>, ["~> 3.10"])
42
42
  s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
43
43
  s.add_dependency(%q<hoe>, ["~> 3.0"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.b4
4
+ version: 2.0.0.b5
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,30 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-13 00:00:00.000000000 Z
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '1.1'
22
+ - - <
20
23
  - !ruby/object:Gem::Version
21
- version: '1.2'
24
+ version: '2.0'
22
25
  type: :runtime
23
26
  prerelease: false
24
27
  version_requirements: !ruby/object:Gem::Requirement
25
28
  none: false
26
29
  requirements:
27
- - - ~>
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '1.1'
33
+ - - <
28
34
  - !ruby/object:Gem::Version
29
- version: '1.2'
35
+ version: '2.0'
30
36
  - !ruby/object:Gem::Dependency
31
37
  name: rdoc
32
38
  requirement: !ruby/object:Gem::Requirement
@@ -161,6 +167,7 @@ files:
161
167
  - lib/puma/reactor.rb
162
168
  - lib/puma/server.rb
163
169
  - lib/puma/thread_pool.rb
170
+ - lib/puma/util.rb
164
171
  - lib/rack/handler/puma.rb
165
172
  - puma.gemspec
166
173
  - tools/jungle/README.md
@@ -204,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
211
  version: 1.3.1
205
212
  requirements: []
206
213
  rubyforge_project: puma
207
- rubygems_version: 1.8.24
214
+ rubygems_version: 1.8.25
208
215
  signing_key:
209
216
  specification_version: 3
210
217
  summary: Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web