unicorn 4.7.0 → 4.8.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/GIT-VERSION-GEN +1 -1
- data/SIGNALS +11 -2
- data/lib/unicorn.rb +5 -0
- data/lib/unicorn/http_server.rb +47 -51
- data/lib/unicorn/stream_input.rb +1 -4
- data/lib/unicorn/worker.rb +64 -0
- data/t/t0300-no-default-middleware.sh +6 -1
- data/test/unit/test_socket_helper.rb +4 -2
- metadata +43 -88
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
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
|
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:
|
data/lib/unicorn/http_server.rb
CHANGED
@@ -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
|
46
|
-
#
|
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
|
-
|
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
|
140
|
-
#
|
141
|
-
#
|
142
|
-
self.pid = config[:pid]
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
#
|
649
|
-
|
650
|
-
trap(:
|
651
|
-
|
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
|
-
|
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
|
672
|
-
|
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(
|
678
|
+
ret = IO.select(readers, nil, nil, @timeout) and ready = ret[0]
|
681
679
|
rescue => e
|
682
|
-
redo if nr < 0
|
683
|
-
Unicorn.log_error(@logger, "listen loop error", e) if
|
684
|
-
end while
|
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
|
-
|
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
|
data/lib/unicorn/stream_input.rb
CHANGED
@@ -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
|
data/lib/unicorn/worker.rb
CHANGED
@@ -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
|
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
|
-
|
194
|
-
|
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:
|
3
|
-
dW5pY29ybg==
|
2
|
+
name: unicorn
|
4
3
|
version: !ruby/object:Gem::Version
|
5
|
-
version: 4.
|
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
|
+
date: 2013-12-09 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
15
13
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
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:
|
34
|
-
a2dpbw==
|
28
|
+
name: kgio
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
|
-
none: false
|
37
30
|
requirements:
|
38
|
-
- -
|
39
|
-
fj4=
|
31
|
+
- - ~>
|
40
32
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
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
|
-
- -
|
49
|
-
fj4=
|
38
|
+
- - ~>
|
50
39
|
- !ruby/object:Gem::Version
|
51
|
-
version:
|
52
|
-
Mi42
|
40
|
+
version: '2.6'
|
53
41
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
55
|
-
cmFpbmRyb3Bz
|
42
|
+
name: raindrops
|
56
43
|
requirement: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
44
|
requirements:
|
59
|
-
- -
|
60
|
-
fj4=
|
45
|
+
- - ~>
|
61
46
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
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
|
-
- -
|
70
|
-
fj4=
|
52
|
+
- - ~>
|
71
53
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
73
|
-
MC43
|
54
|
+
version: '0.7'
|
74
55
|
- !ruby/object:Gem::Dependency
|
75
|
-
name:
|
76
|
-
aXNvbGF0ZQ==
|
56
|
+
name: isolate
|
77
57
|
requirement: !ruby/object:Gem::Requirement
|
78
|
-
none: false
|
79
58
|
requirements:
|
80
|
-
- -
|
81
|
-
fj4=
|
59
|
+
- - ~>
|
82
60
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
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
|
-
- -
|
91
|
-
fj4=
|
66
|
+
- - ~>
|
92
67
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
94
|
-
My4y
|
68
|
+
version: '3.2'
|
95
69
|
- !ruby/object:Gem::Dependency
|
96
|
-
name:
|
97
|
-
d3Jvbmdkb2M=
|
70
|
+
name: wrongdoc
|
98
71
|
requirement: !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
72
|
requirements:
|
101
|
-
- -
|
102
|
-
fj4=
|
73
|
+
- - ~>
|
103
74
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
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
|
-
- -
|
112
|
-
fj4=
|
80
|
+
- - ~>
|
113
81
|
- !ruby/object:Gem::Version
|
114
|
-
version:
|
115
|
-
|
116
|
-
|
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
|
-
|
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
|
-
-
|
130
|
-
|
131
|
-
- !binary |-
|
132
|
-
dW5pY29ybl9yYWlscw==
|
91
|
+
- unicorn
|
92
|
+
- unicorn_rails
|
133
93
|
extensions:
|
134
|
-
-
|
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
|
-
-
|
334
|
-
|
335
|
-
|
336
|
-
UnVieSAxLjg=
|
292
|
+
- GPLv2+
|
293
|
+
- Ruby 1.8
|
294
|
+
metadata: {}
|
337
295
|
post_install_message:
|
338
296
|
rdoc_options:
|
339
297
|
- -t
|
340
|
-
-
|
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:
|
312
|
+
version: 1.3.1
|
357
313
|
requirements: []
|
358
|
-
rubyforge_project:
|
359
|
-
|
360
|
-
rubygems_version: 1.8.23
|
314
|
+
rubyforge_project: mongrel
|
315
|
+
rubygems_version: 2.1.9
|
361
316
|
signing_key:
|
362
|
-
specification_version:
|
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
|