unicorn 4.7.0 → 4.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a2554354da992cb50d7fb537e1f0e71834d3a82c
4
+ data.tar.gz: 211ee8070608c0db6a605453061cb22059c92912
5
+ SHA512:
6
+ metadata.gz: 0b9d4e9734fa2a501571e0ca97b36c9a9bef4b44985939bb3eaafac5dcbe473b8b38582cf2b076f0dcc2c2b19bc93ed0ee14934348d36483cb84f22d655fce21
7
+ data.tar.gz: 4b68dba9d31fb5352e4ee9e7b6313910f728a6293ab0c35c7944357ea6eef6c7870c502ec15b2df32c6618eb0ec5e0a3248bd8767447dbc9def526f9246cbc88
data/GIT-VERSION-GEN CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- DEF_VER = "v4.7.0"
2
+ DEF_VER = "v4.8.0.pre1"
3
3
  CONSTANT = "Unicorn::Const::UNICORN_VERSION"
4
4
  RVF = "lib/unicorn/version.rb"
5
5
  GVF = "GIT-VERSION-FILE"
data/SIGNALS CHANGED
@@ -7,6 +7,9 @@ signal handling matches the behavior of {nginx}[http://nginx.net/] so it
7
7
  should be possible to easily share process management scripts between
8
8
  Unicorn and nginx.
9
9
 
10
+ One example init script is distributed with unicorn:
11
+ http://unicorn.bogomips.org/examples/init.sh
12
+
10
13
  === Master Process
11
14
 
12
15
  * HUP - reloads config file and gracefully restart all workers.
@@ -42,6 +45,10 @@ Unicorn and nginx.
42
45
 
43
46
  === Worker Processes
44
47
 
48
+ Note: as of unicorn 4.8, the master uses a pipe to signal workers
49
+ instead of kill(2) for most cases. Using signals still (and works and
50
+ remains supported for external tools/libraries), however.
51
+
45
52
  Sending signals directly to the worker processes should not normally be
46
53
  needed. If the master process is running, any exited worker will be
47
54
  automatically respawned.
@@ -49,6 +56,8 @@ automatically respawned.
49
56
  * INT/TERM - Quick shutdown, immediately exit.
50
57
  Unless WINCH has been sent to the master (or the master is killed),
51
58
  the master process will respawn a worker to replace this one.
59
+ Immediate shutdown is still triggered using kill(2) and not the
60
+ internal pipe as of unicorn 4.8
52
61
 
53
62
  * QUIT - Gracefully exit after finishing the current request.
54
63
  Unless WINCH has been sent to the master (or the master is killed),
@@ -101,8 +110,8 @@ The procedure is exactly like that of nginx:
101
110
 
102
111
  3. You can now send WINCH to the old master process so only the new workers
103
112
  serve requests. If your unicorn process is bound to an interactive
104
- terminal, you can skip this step. Step 5 will be more difficult but
105
- you can also skip it if your process is not daemonized.
113
+ terminal (not daemonized), you can skip this step. Step 5 will be more
114
+ difficult but you can also skip it if your process is not daemonized.
106
115
 
107
116
  4. You should now ensure that everything is running correctly with the
108
117
  new workers as the old workers die off.
data/lib/unicorn.rb CHANGED
@@ -97,6 +97,11 @@ module Unicorn
97
97
  logger.error "#{prefix}: #{message} (#{exc.class})"
98
98
  exc.backtrace.each { |line| logger.error(line) }
99
99
  end
100
+
101
+ # remove this when we only support Ruby >= 2.0
102
+ def self.pipe # :nodoc:
103
+ Kgio::Pipe.new.each { |io| io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) }
104
+ end
100
105
  # :startdoc:
101
106
  end
102
107
  # :enddoc:
@@ -42,16 +42,8 @@ class Unicorn::HttpServer
42
42
  # it to wake up the master from IO.select in exactly the same manner
43
43
  # djb describes in http://cr.yp.to/docs/selfpipe.html
44
44
  #
45
- # * The workers immediately close the pipe they inherit from the
46
- # master and replace it with a new pipe after forking. This new
47
- # pipe is also used to wakeup from IO.select from inside (worker)
48
- # signal handlers. However, workers *close* the pipe descriptors in
49
- # the signal handlers to raise EBADF in IO.select instead of writing
50
- # like we do in the master. We cannot easily use the reader set for
51
- # IO.select because LISTENERS is already that set, and it's extra
52
- # work (and cycles) to distinguish the pipe FD from the reader set
53
- # once IO.select returns. So we're lazy and just close the pipe when
54
- # a (rare) signal arrives in the worker and reinitialize the pipe later.
45
+ # * The workers immediately close the pipe they inherit. See the
46
+ # Unicorn::Worker class for the pipe workers use.
55
47
  SELF_PIPE = []
56
48
 
57
49
  # signal queue used for self-piping
@@ -127,7 +119,7 @@ class Unicorn::HttpServer
127
119
  inherit_listeners!
128
120
  # this pipe is used to wake us up from select(2) in #join when signals
129
121
  # are trapped. See trap_deferred.
130
- init_self_pipe!
122
+ SELF_PIPE.replace(Unicorn.pipe)
131
123
 
132
124
  # setup signal handlers before writing pid file in case people get
133
125
  # trigger happy and send signals as soon as the pid file exists.
@@ -136,20 +128,15 @@ class Unicorn::HttpServer
136
128
  trap(:CHLD) { awaken_master }
137
129
 
138
130
  # write pid early for Mongrel compatibility if we're not inheriting sockets
139
- # This was needed for compatibility with some health checker a long time
140
- # ago. This unfortunately has the side effect of clobbering valid PID
141
- # files.
142
- self.pid = config[:pid] unless ENV["UNICORN_FD"]
131
+ # This is needed for compatibility some Monit setups at least.
132
+ # This unfortunately has the side effect of clobbering valid PID if
133
+ # we upgrade and the upgrade breaks during preload_app==true && build_app!
134
+ self.pid = config[:pid]
143
135
 
144
136
  self.master_pid = $$
145
137
  build_app! if preload_app
146
138
  bind_new_listeners!
147
139
 
148
- # Assuming preload_app==false, we drop the pid file after the app is ready
149
- # to process requests. If binding or build_app! fails with
150
- # preload_app==true, we'll never get here and the parent will recover
151
- self.pid = config[:pid] if ENV["UNICORN_FD"]
152
-
153
140
  spawn_missing_workers
154
141
  self
155
142
  end
@@ -311,14 +298,14 @@ class Unicorn::HttpServer
311
298
  logger.info "master reopening logs..."
312
299
  Unicorn::Util.reopen_logs
313
300
  logger.info "master done reopening logs"
314
- kill_each_worker(:USR1)
301
+ soft_kill_each_worker(:USR1)
315
302
  when :USR2 # exec binary, stay alive in case something went wrong
316
303
  reexec
317
304
  when :WINCH
318
305
  if Unicorn::Configurator::RACKUP[:daemonized]
319
306
  respawn = false
320
307
  logger.info "gracefully stopping all workers"
321
- kill_each_worker(:QUIT)
308
+ soft_kill_each_worker(:QUIT)
322
309
  self.worker_processes = 0
323
310
  else
324
311
  logger.info "SIGWINCH ignored because we're not daemonized"
@@ -350,7 +337,11 @@ class Unicorn::HttpServer
350
337
  self.listeners = []
351
338
  limit = Time.now + timeout
352
339
  until WORKERS.empty? || Time.now > limit
353
- kill_each_worker(graceful ? :QUIT : :TERM)
340
+ if graceful
341
+ soft_kill_each_worker(:QUIT)
342
+ else
343
+ kill_each_worker(:TERM)
344
+ end
354
345
  sleep(0.1)
355
346
  reap_all_workers
356
347
  end
@@ -503,6 +494,7 @@ class Unicorn::HttpServer
503
494
  end
504
495
 
505
496
  def after_fork_internal
497
+ SELF_PIPE.each { |io| io.close }.clear # this is master-only, now
506
498
  @ready_pipe.close if @ready_pipe
507
499
  Unicorn::Configurator::RACKUP.clear
508
500
  @ready_pipe = @init_listeners = @before_exec = @before_fork = nil
@@ -522,6 +514,7 @@ class Unicorn::HttpServer
522
514
  before_fork.call(self, worker)
523
515
  if pid = fork
524
516
  WORKERS[pid] = worker
517
+ worker.atfork_parent
525
518
  else
526
519
  after_fork_internal
527
520
  worker_loop(worker)
@@ -536,9 +529,7 @@ class Unicorn::HttpServer
536
529
  def maintain_worker_count
537
530
  (off = WORKERS.size - worker_processes) == 0 and return
538
531
  off < 0 and return spawn_missing_workers
539
- WORKERS.dup.each_pair { |wpid,w|
540
- w.nr >= worker_processes and kill_worker(:QUIT, wpid) rescue nil
541
- }
532
+ WORKERS.each_value { |w| w.nr >= worker_processes and w.soft_kill(:QUIT) }
542
533
  end
543
534
 
544
535
  # if we get any error, try to write something back to the client
@@ -605,6 +596,7 @@ class Unicorn::HttpServer
605
596
  # traps for USR1, USR2, and HUP may be set in the after_fork Proc
606
597
  # by the user.
607
598
  def init_worker_process(worker)
599
+ worker.atfork_child
608
600
  # we'll re-trap :QUIT later for graceful shutdown iff we accept clients
609
601
  EXIT_SIGS.each { |sig| trap(sig) { exit!(0) } }
610
602
  exit!(0) if (SIG_QUEUE & EXIT_SIGS)[0]
@@ -613,23 +605,27 @@ class Unicorn::HttpServer
613
605
  SIG_QUEUE.clear
614
606
  proc_name "worker[#{worker.nr}]"
615
607
  START_CTX.clear
616
- init_self_pipe!
617
608
  WORKERS.clear
609
+
610
+ after_fork.call(self, worker) # can drop perms and create listeners
618
611
  LISTENERS.each { |sock| sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) }
619
- after_fork.call(self, worker) # can drop perms
612
+
620
613
  worker.user(*user) if user.kind_of?(Array) && ! worker.switched
621
614
  self.timeout /= 2.0 # halve it for select()
622
615
  @config = nil
623
616
  build_app! unless preload_app
624
617
  ssl_enable!
625
618
  @after_fork = @listener_opts = @orig_app = nil
619
+ readers = LISTENERS.dup
620
+ readers << worker
621
+ trap(:QUIT) { readers.each { |io| io.close }.replace([false]) }
622
+ readers
626
623
  end
627
624
 
628
625
  def reopen_worker_logs(worker_nr)
629
626
  logger.info "worker=#{worker_nr} reopening logs..."
630
627
  Unicorn::Util.reopen_logs
631
628
  logger.info "worker=#{worker_nr} done reopening logs"
632
- init_self_pipe!
633
629
  rescue => e
634
630
  logger.error(e) rescue nil
635
631
  exit!(77) # EX_NOPERM in sysexits.h
@@ -640,22 +636,24 @@ class Unicorn::HttpServer
640
636
  # given a INT, QUIT, or TERM signal)
641
637
  def worker_loop(worker)
642
638
  ppid = master_pid
643
- init_worker_process(worker)
639
+ readers = init_worker_process(worker)
644
640
  nr = 0 # this becomes negative if we need to reopen logs
645
- l = LISTENERS.dup
646
- ready = l.dup
647
641
 
648
- # closing anything we IO.select on will raise EBADF
649
- trap(:USR1) { nr = -65536; SELF_PIPE[0].close rescue nil }
650
- trap(:QUIT) { worker = nil; LISTENERS.each { |s| s.close rescue nil }.clear }
651
- logger.info "worker=#{worker.nr} ready"
642
+ # this only works immediately if the master sent us the signal
643
+ # (which is the normal case)
644
+ trap(:USR1) { nr = -65536 }
645
+
646
+ ready = readers.dup
647
+ @logger.info "worker=#{worker.nr} ready"
652
648
 
653
649
  begin
654
650
  nr < 0 and reopen_worker_logs(worker.nr)
655
651
  nr = 0
656
-
657
652
  worker.tick = Time.now.to_i
658
- while sock = ready.shift
653
+ tmp = ready.dup
654
+ while sock = tmp.shift
655
+ # Unicorn::Worker#kgio_tryaccept is not like accept(2) at all,
656
+ # but that will return false
659
657
  if client = sock.kgio_tryaccept
660
658
  process_client(client)
661
659
  nr += 1
@@ -668,8 +666,8 @@ class Unicorn::HttpServer
668
666
  # we're probably reasonably busy, so avoid calling select()
669
667
  # and do a speculative non-blocking accept() on ready listeners
670
668
  # before we sleep again in select().
671
- unless nr == 0 # (nr < 0) => reopen logs (unlikely)
672
- ready = l.dup
669
+ unless nr == 0
670
+ tmp = ready.dup
673
671
  redo
674
672
  end
675
673
 
@@ -677,11 +675,11 @@ class Unicorn::HttpServer
677
675
 
678
676
  # timeout used so we can detect parent death:
679
677
  worker.tick = Time.now.to_i
680
- ret = IO.select(l, nil, SELF_PIPE, @timeout) and ready = ret[0]
678
+ ret = IO.select(readers, nil, nil, @timeout) and ready = ret[0]
681
679
  rescue => e
682
- redo if nr < 0 && (Errno::EBADF === e || IOError === e) # reopen logs
683
- Unicorn.log_error(@logger, "listen loop error", e) if worker
684
- end while worker
680
+ redo if nr < 0
681
+ Unicorn.log_error(@logger, "listen loop error", e) if readers[0]
682
+ end while readers[0]
685
683
  end
686
684
 
687
685
  # delivers a signal to a worker and fails gracefully if the worker
@@ -697,6 +695,10 @@ class Unicorn::HttpServer
697
695
  WORKERS.keys.each { |wpid| kill_worker(signal, wpid) }
698
696
  end
699
697
 
698
+ def soft_kill_each_worker(signal)
699
+ WORKERS.each_value { |worker| worker.soft_kill(signal) }
700
+ end
701
+
700
702
  # unlinks a PID file at given +path+ if it contains the current PID
701
703
  # still potentially racy without locking the directory (which is
702
704
  # non-portable and may interact badly with other programs), but the
@@ -725,7 +727,7 @@ class Unicorn::HttpServer
725
727
  config[:listeners].replace(@init_listeners)
726
728
  config.reload
727
729
  config.commit!(self)
728
- kill_each_worker(:QUIT)
730
+ soft_kill_each_worker(:QUIT)
729
731
  Unicorn::Util.reopen_logs
730
732
  self.app = orig_app
731
733
  build_app! if preload_app
@@ -761,12 +763,6 @@ class Unicorn::HttpServer
761
763
  io.sync = true
762
764
  end
763
765
 
764
- def init_self_pipe!
765
- SELF_PIPE.each { |io| io.close rescue nil }
766
- SELF_PIPE.replace(Kgio::Pipe.new)
767
- SELF_PIPE.each { |io| io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) }
768
- end
769
-
770
766
  def inherit_listeners!
771
767
  # inherit sockets from parents, they need to be plain Socket objects
772
768
  # before they become Kgio::UNIXServer or Kgio::TCPServer
@@ -139,10 +139,7 @@ private
139
139
  # we do support clients that shutdown(SHUT_WR) after the
140
140
  # _entire_ request has been sent, and those will not have
141
141
  # raised EOFError on us.
142
- if @socket
143
- @socket.shutdown
144
- @socket.close
145
- end
142
+ @socket.shutdown if @socket
146
143
  ensure
147
144
  raise Unicorn::ClientShutdown, "bytes_read=#{@bytes_read}", []
148
145
  end
@@ -12,6 +12,7 @@ class Unicorn::Worker
12
12
  # :stopdoc:
13
13
  attr_accessor :nr, :switched
14
14
  attr_writer :tmp
15
+ attr_reader :to_io # IO.select-compatible
15
16
 
16
17
  PER_DROP = Raindrops::PAGE_SIZE / Raindrops::SIZE
17
18
  DROPS = []
@@ -23,6 +24,66 @@ class Unicorn::Worker
23
24
  @raindrop[@offset] = 0
24
25
  @nr = nr
25
26
  @tmp = @switched = false
27
+ @to_io, @master = Unicorn.pipe
28
+ end
29
+
30
+ def atfork_child # :nodoc:
31
+ # we _must_ close in child, parent just holds this open to signal
32
+ @master = @master.close
33
+ end
34
+
35
+ # master fakes SIGQUIT using this
36
+ def quit # :nodoc:
37
+ @master = @master.close if @master
38
+ end
39
+
40
+ # parent does not read
41
+ def atfork_parent # :nodoc:
42
+ @to_io = @to_io.close
43
+ end
44
+
45
+ # call a signal handler immediately without triggering EINTR
46
+ # We do not use the more obvious Process.kill(sig, $$) here since
47
+ # that signal delivery may be deferred. We want to avoid signal delivery
48
+ # while the Rack app.call is running because some database drivers
49
+ # (e.g. ruby-pg) may cancel pending requests.
50
+ def fake_sig(sig) # :nodoc:
51
+ old_cb = trap(sig, "IGNORE")
52
+ old_cb.call
53
+ ensure
54
+ trap(sig, old_cb)
55
+ end
56
+
57
+ # master sends fake signals to children
58
+ def soft_kill(sig) # :nodoc:
59
+ case sig
60
+ when Integer
61
+ signum = sig
62
+ else
63
+ signum = Signal.list[sig.to_s] or
64
+ raise ArgumentError, "BUG: bad signal: #{sig.inspect}"
65
+ end
66
+ # writing and reading 4 bytes on a pipe is atomic on all POSIX platforms
67
+ # Do not care in the odd case the buffer is full, here.
68
+ @master.kgio_trywrite([signum].pack('l'))
69
+ rescue Errno::EPIPE
70
+ # worker will be reaped soon
71
+ end
72
+
73
+ # this only runs when the Rack app.call is not running
74
+ # act like a listener
75
+ def kgio_tryaccept # :nodoc:
76
+ case buf = @to_io.kgio_tryread(4)
77
+ when String
78
+ # unpack the buffer and trigger the signal handler
79
+ signum = buf.unpack('l')
80
+ fake_sig(signum[0])
81
+ # keep looping, more signals may be queued
82
+ when nil # EOF: master died, but we are at a safe place to exit
83
+ fake_sig(:QUIT)
84
+ when :wait_readable # keep waiting
85
+ return false
86
+ end while true # loop, as multiple signals may be sent
26
87
  end
27
88
 
28
89
  # worker objects may be compared to just plain Integers
@@ -49,8 +110,11 @@ class Unicorn::Worker
49
110
  end
50
111
  end
51
112
 
113
+ # called in both the master (reaping worker) and worker (SIGQUIT handler)
52
114
  def close # :nodoc:
53
115
  @tmp.close if @tmp
116
+ @master.close if @master
117
+ @to_io.close if @to_io
54
118
  end
55
119
 
56
120
  # :startdoc:
@@ -1,6 +1,6 @@
1
1
  #!/bin/sh
2
2
  . ./test-lib.sh
3
- t_plan 2 "test the -N / --no-default-middleware option"
3
+ t_plan 3 "test the -N / --no-default-middleware option"
4
4
 
5
5
  t_begin "setup and start" && {
6
6
  unicorn_setup
@@ -12,4 +12,9 @@ t_begin "check exit status with Rack::Lint not present" && {
12
12
  test 42 -eq "$(curl -sf -o/dev/null -w'%{http_code}' http://$listen/)"
13
13
  }
14
14
 
15
+ t_begin "killing succeeds" && {
16
+ kill $unicorn_pid
17
+ check_stderr
18
+ }
19
+
15
20
  t_done
@@ -190,6 +190,8 @@ class TestSocketHelper < Test::Unit::TestCase
190
190
  name = "#@test_addr:#{port}"
191
191
  sock = bind_listen(name, :reuseport => true)
192
192
  cur = sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).unpack('i')[0]
193
- assert_equal 1, cur
194
- end if defined?(SO_REUSEPORT)
193
+ assert_operator cur, :>, 0
194
+ rescue Errno::ENOPROTOOPT
195
+ # kernel does not support SO_REUSEPORT (older Linux)
196
+ end
195
197
  end
metadata CHANGED
@@ -1,138 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
- name: !binary |-
3
- dW5pY29ybg==
2
+ name: unicorn
4
3
  version: !ruby/object:Gem::Version
5
- version: 4.7.0
6
- prerelease:
4
+ version: 4.8.0.pre1
7
5
  platform: ruby
8
6
  authors:
9
7
  - Unicorn hackers
10
8
  autorequire:
11
9
  bindir: bin
12
10
  cert_chain: []
13
- date: 2013-11-04 00:00:00.000000000 Z
11
+ date: 2013-12-09 00:00:00.000000000 Z
14
12
  dependencies:
15
13
  - !ruby/object:Gem::Dependency
16
- name: !binary |-
17
- cmFjaw==
14
+ name: rack
18
15
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
16
  requirements:
21
- - - ! '>='
17
+ - - '>='
22
18
  - !ruby/object:Gem::Version
23
19
  version: '0'
24
20
  type: :runtime
25
21
  prerelease: false
26
22
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
23
  requirements:
29
- - - ! '>='
24
+ - - '>='
30
25
  - !ruby/object:Gem::Version
31
26
  version: '0'
32
27
  - !ruby/object:Gem::Dependency
33
- name: !binary |-
34
- a2dpbw==
28
+ name: kgio
35
29
  requirement: !ruby/object:Gem::Requirement
36
- none: false
37
30
  requirements:
38
- - - !binary |-
39
- fj4=
31
+ - - ~>
40
32
  - !ruby/object:Gem::Version
41
- version: !binary |-
42
- Mi42
33
+ version: '2.6'
43
34
  type: :runtime
44
35
  prerelease: false
45
36
  version_requirements: !ruby/object:Gem::Requirement
46
- none: false
47
37
  requirements:
48
- - - !binary |-
49
- fj4=
38
+ - - ~>
50
39
  - !ruby/object:Gem::Version
51
- version: !binary |-
52
- Mi42
40
+ version: '2.6'
53
41
  - !ruby/object:Gem::Dependency
54
- name: !binary |-
55
- cmFpbmRyb3Bz
42
+ name: raindrops
56
43
  requirement: !ruby/object:Gem::Requirement
57
- none: false
58
44
  requirements:
59
- - - !binary |-
60
- fj4=
45
+ - - ~>
61
46
  - !ruby/object:Gem::Version
62
- version: !binary |-
63
- MC43
47
+ version: '0.7'
64
48
  type: :runtime
65
49
  prerelease: false
66
50
  version_requirements: !ruby/object:Gem::Requirement
67
- none: false
68
51
  requirements:
69
- - - !binary |-
70
- fj4=
52
+ - - ~>
71
53
  - !ruby/object:Gem::Version
72
- version: !binary |-
73
- MC43
54
+ version: '0.7'
74
55
  - !ruby/object:Gem::Dependency
75
- name: !binary |-
76
- aXNvbGF0ZQ==
56
+ name: isolate
77
57
  requirement: !ruby/object:Gem::Requirement
78
- none: false
79
58
  requirements:
80
- - - !binary |-
81
- fj4=
59
+ - - ~>
82
60
  - !ruby/object:Gem::Version
83
- version: !binary |-
84
- My4y
61
+ version: '3.2'
85
62
  type: :development
86
63
  prerelease: false
87
64
  version_requirements: !ruby/object:Gem::Requirement
88
- none: false
89
65
  requirements:
90
- - - !binary |-
91
- fj4=
66
+ - - ~>
92
67
  - !ruby/object:Gem::Version
93
- version: !binary |-
94
- My4y
68
+ version: '3.2'
95
69
  - !ruby/object:Gem::Dependency
96
- name: !binary |-
97
- d3Jvbmdkb2M=
70
+ name: wrongdoc
98
71
  requirement: !ruby/object:Gem::Requirement
99
- none: false
100
72
  requirements:
101
- - - !binary |-
102
- fj4=
73
+ - - ~>
103
74
  - !ruby/object:Gem::Version
104
- version: !binary |-
105
- MS42LjE=
75
+ version: 1.6.1
106
76
  type: :development
107
77
  prerelease: false
108
78
  version_requirements: !ruby/object:Gem::Requirement
109
- none: false
110
79
  requirements:
111
- - - !binary |-
112
- fj4=
80
+ - - ~>
113
81
  - !ruby/object:Gem::Version
114
- version: !binary |-
115
- MS42LjE=
116
- description: ! '\Unicorn is an HTTP server for Rack applications designed to only
117
- serve
118
-
82
+ version: 1.6.1
83
+ description: |-
84
+ \Unicorn is an HTTP server for Rack applications designed to only serve
119
85
  fast clients on low-latency, high-bandwidth connections and take
120
-
121
86
  advantage of features in Unix/Unix-like kernels. Slow clients should
122
-
123
87
  only be served by placing a reverse proxy capable of fully buffering
124
-
125
- both the the request and response in between \Unicorn and slow clients.'
126
- email: !binary |-
127
- bW9uZ3JlbC11bmljb3JuQHJ1Ynlmb3JnZS5vcmc=
88
+ both the the request and response in between \Unicorn and slow clients.
89
+ email: mongrel-unicorn@rubyforge.org
128
90
  executables:
129
- - !binary |-
130
- dW5pY29ybg==
131
- - !binary |-
132
- dW5pY29ybl9yYWlscw==
91
+ - unicorn
92
+ - unicorn_rails
133
93
  extensions:
134
- - !binary |-
135
- ZXh0L3VuaWNvcm5faHR0cC9leHRjb25mLnJi
94
+ - ext/unicorn_http/extconf.rb
136
95
  extra_rdoc_files:
137
96
  - FAQ
138
97
  - README
@@ -330,36 +289,32 @@ files:
330
289
  - unicorn.gemspec
331
290
  homepage: http://unicorn.bogomips.org/
332
291
  licenses:
333
- - !binary |-
334
- R1BMdjIr
335
- - !binary |-
336
- UnVieSAxLjg=
292
+ - GPLv2+
293
+ - Ruby 1.8
294
+ metadata: {}
337
295
  post_install_message:
338
296
  rdoc_options:
339
297
  - -t
340
- - ! 'Unicorn: Rack HTTP server for fast clients and Unix'
298
+ - 'Unicorn: Rack HTTP server for fast clients and Unix'
341
299
  - -W
342
300
  - http://bogomips.org/unicorn.git/tree/%s
343
301
  require_paths:
344
302
  - lib
345
303
  required_ruby_version: !ruby/object:Gem::Requirement
346
- none: false
347
304
  requirements:
348
- - - ! '>='
305
+ - - '>='
349
306
  - !ruby/object:Gem::Version
350
307
  version: '0'
351
308
  required_rubygems_version: !ruby/object:Gem::Requirement
352
- none: false
353
309
  requirements:
354
- - - ! '>='
310
+ - - '>'
355
311
  - !ruby/object:Gem::Version
356
- version: '0'
312
+ version: 1.3.1
357
313
  requirements: []
358
- rubyforge_project: !binary |-
359
- bW9uZ3JlbA==
360
- rubygems_version: 1.8.23
314
+ rubyforge_project: mongrel
315
+ rubygems_version: 2.1.9
361
316
  signing_key:
362
- specification_version: 3
317
+ specification_version: 4
363
318
  summary: Rack HTTP server for fast clients and Unix
364
319
  test_files:
365
320
  - test/unit/test_configurator.rb