rainbows 0.90.2 → 0.91.0
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.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +1 -1
- data/bin/rainbows +3 -41
- data/lib/rainbows.rb +13 -24
- data/lib/rainbows/const.rb +1 -1
- data/lib/rainbows/error.rb +2 -1
- data/lib/rainbows/ev_core.rb +1 -1
- data/lib/rainbows/fiber/base.rb +4 -6
- data/lib/rainbows/fiber/io.rb +3 -1
- data/lib/rainbows/rev.rb +5 -0
- data/lib/rainbows/revactor.rb +6 -5
- data/lib/rainbows/revactor/tee_input.rb +2 -2
- data/rainbows.gemspec +1 -1
- data/t/t0013-reload-bad-config.sh +54 -0
- data/t/t0014-config-conflict.sh +50 -0
- data/t/test-lib.sh +1 -7
- metadata +4 -5
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
data/bin/rainbows
CHANGED
@@ -113,49 +113,11 @@ end
|
|
113
113
|
config = ARGV[0] || "config.ru"
|
114
114
|
abort "configuration file #{config} not found" unless File.exist?(config)
|
115
115
|
|
116
|
-
|
117
|
-
# parse embedded command-line options in config.ru comments
|
118
|
-
if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
|
119
|
-
opts.parse! $1.split(/\s+/)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
require 'pp' if $DEBUG
|
124
|
-
|
125
|
-
app = lambda do ||
|
126
|
-
# require Rack as late as possible in case $LOAD_PATH is modified
|
127
|
-
# in config.ru or command-line
|
128
|
-
inner_app = case config
|
129
|
-
when /\.ru$/
|
130
|
-
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
131
|
-
raw.sub!(/^__END__\n.*/, '')
|
132
|
-
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
133
|
-
else
|
134
|
-
require config
|
135
|
-
Object.const_get(File.basename(config, '.rb').capitalize)
|
136
|
-
end
|
137
|
-
pp({ :inner_app => inner_app }) if $DEBUG
|
138
|
-
case ENV["RACK_ENV"]
|
139
|
-
when "development"
|
140
|
-
Rack::Builder.new do
|
141
|
-
use Rack::CommonLogger, $stderr
|
142
|
-
use Rack::ShowExceptions
|
143
|
-
use Rack::Lint
|
144
|
-
run inner_app
|
145
|
-
end.to_app
|
146
|
-
when "deployment"
|
147
|
-
Rack::Builder.new do
|
148
|
-
use Rack::CommonLogger, $stderr
|
149
|
-
run inner_app
|
150
|
-
end.to_app
|
151
|
-
else
|
152
|
-
inner_app
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
116
|
+
app = Unicorn.builder(config, opts)
|
156
117
|
listeners << "#{host}:#{port}" if set_listener
|
157
118
|
|
158
119
|
if $DEBUG
|
120
|
+
require 'pp'
|
159
121
|
pp({
|
160
122
|
:unicorn_options => options,
|
161
123
|
:app => app,
|
@@ -163,5 +125,5 @@ if $DEBUG
|
|
163
125
|
})
|
164
126
|
end
|
165
127
|
|
166
|
-
Unicorn::Launcher.daemonize! if daemonize
|
128
|
+
Unicorn::Launcher.daemonize!(options) if daemonize
|
167
129
|
Rainbows.run(app, options)
|
data/lib/rainbows.rb
CHANGED
@@ -22,7 +22,7 @@ module Rainbows
|
|
22
22
|
false
|
23
23
|
end
|
24
24
|
end
|
25
|
-
G = State.new(true, 0, 0,
|
25
|
+
G = State.new(true, 0, 0, 5)
|
26
26
|
O = {}
|
27
27
|
|
28
28
|
require 'rainbows/const'
|
@@ -59,30 +59,19 @@ module Rainbows
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# returns nil if accept fails
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def accept(sock)
|
71
|
-
rv = sock.accept_nonblock
|
72
|
-
rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
73
|
-
rv
|
74
|
-
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
75
|
-
end
|
76
|
-
else
|
77
|
-
def sync_accept(sock)
|
78
|
-
sock.accept
|
79
|
-
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR
|
80
|
-
end
|
62
|
+
def sync_accept(sock)
|
63
|
+
rv = sock.accept
|
64
|
+
rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
65
|
+
rv
|
66
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR
|
67
|
+
end
|
81
68
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
69
|
+
# returns nil if accept fails
|
70
|
+
def accept(sock)
|
71
|
+
rv = sock.accept_nonblock
|
72
|
+
rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
73
|
+
rv
|
74
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
86
75
|
end
|
87
76
|
end
|
88
77
|
|
data/lib/rainbows/const.rb
CHANGED
data/lib/rainbows/error.rb
CHANGED
@@ -28,7 +28,8 @@ module Rainbows
|
|
28
28
|
|
29
29
|
def response(e)
|
30
30
|
case e
|
31
|
-
when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,
|
31
|
+
when EOFError, Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL,
|
32
|
+
Errno::EBADF, Errno::ENOTCONN
|
32
33
|
# swallow error if client shuts down one end or disconnects
|
33
34
|
when Unicorn::HttpParserError
|
34
35
|
Const::ERROR_400_RESPONSE # try to tell the client they're bad
|
data/lib/rainbows/ev_core.rb
CHANGED
data/lib/rainbows/fiber/base.rb
CHANGED
@@ -5,13 +5,13 @@ module Rainbows
|
|
5
5
|
module Fiber
|
6
6
|
|
7
7
|
# blocked readers (key: Rainbows::Fiber::IO object, value is irrelevant)
|
8
|
-
RD = {}
|
8
|
+
RD = {}.compare_by_identity
|
9
9
|
|
10
10
|
# blocked writers (key: Rainbows::Fiber::IO object, value is irrelevant)
|
11
|
-
WR = {}
|
11
|
+
WR = {}.compare_by_identity
|
12
12
|
|
13
13
|
# sleeping fibers go here (key: Fiber object, value: wakeup time)
|
14
|
-
ZZ = {}
|
14
|
+
ZZ = {}.compare_by_identity
|
15
15
|
|
16
16
|
# puts the current Fiber into uninterruptible sleep for at least
|
17
17
|
# +seconds+. Unlike Kernel#sleep, this it is not possible to sleep
|
@@ -103,10 +103,8 @@ module Rainbows
|
|
103
103
|
Error.write(io, e)
|
104
104
|
ensure
|
105
105
|
G.cur -= 1
|
106
|
-
RD.delete(client)
|
107
|
-
WR.delete(client)
|
108
106
|
ZZ.delete(client.f)
|
109
|
-
|
107
|
+
client.close
|
110
108
|
end
|
111
109
|
|
112
110
|
end
|
data/lib/rainbows/fiber/io.rb
CHANGED
data/lib/rainbows/rev.rb
CHANGED
data/lib/rainbows/revactor.rb
CHANGED
@@ -30,8 +30,8 @@ module Rainbows
|
|
30
30
|
# once a client is accepted, it is processed in its entirety here
|
31
31
|
# in 3 easy steps: read request, call app, write app response
|
32
32
|
def process_client(client)
|
33
|
-
|
34
|
-
|
33
|
+
io = client.instance_variable_get(:@_io)
|
34
|
+
io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
35
35
|
rd_args = [ nil ]
|
36
36
|
remote_addr = if ::Revactor::TCP::Socket === client
|
37
37
|
rd_args << RD_ARGS
|
@@ -68,7 +68,7 @@ module Rainbows
|
|
68
68
|
end while alive and hp.reset.nil? and env.clear
|
69
69
|
rescue ::Revactor::TCP::ReadError
|
70
70
|
rescue => e
|
71
|
-
Error.write(
|
71
|
+
Error.write(io, e)
|
72
72
|
ensure
|
73
73
|
client.close
|
74
74
|
end
|
@@ -86,7 +86,7 @@ module Rainbows
|
|
86
86
|
revactorize_listeners.each do |l, close, accept|
|
87
87
|
Actor.spawn(l, close, accept) do |l, close, accept|
|
88
88
|
Actor.current.trap_exit = true
|
89
|
-
l.controller = l.
|
89
|
+
l.controller = l.instance_variable_set(:@receiver, Actor.current)
|
90
90
|
begin
|
91
91
|
while nr >= limit
|
92
92
|
l.disable if l.enabled?
|
@@ -118,7 +118,8 @@ module Rainbows
|
|
118
118
|
end
|
119
119
|
|
120
120
|
Actor.sleep 1 while G.tick || nr > 0
|
121
|
-
rescue Errno::EMFILE
|
121
|
+
rescue Errno::EMFILE
|
122
|
+
# ignore, let another worker process take it
|
122
123
|
end
|
123
124
|
|
124
125
|
def revactorize_listeners
|
@@ -22,11 +22,11 @@ module Rainbows
|
|
22
22
|
def tee(length, dst)
|
23
23
|
unless parser.body_eof?
|
24
24
|
if parser.filter_body(dst, buf << socket.read).nil?
|
25
|
-
|
25
|
+
tmp.write(dst)
|
26
26
|
diff = dst.size - length
|
27
27
|
if diff > 0
|
28
28
|
dst.replace(dst[0,length])
|
29
|
-
|
29
|
+
tmp.seek(-diff, IO::SEEK_CUR)
|
30
30
|
end
|
31
31
|
return dst
|
32
32
|
end
|
data/rainbows.gemspec
CHANGED
@@ -43,7 +43,7 @@ Gem::Specification.new do |s|
|
|
43
43
|
# we need Unicorn for the HTTP parser and process management
|
44
44
|
# The HTTP parser in Unicorn < 0.96.1 did not use the Ruby
|
45
45
|
# API correctly and resulted in a memory leak
|
46
|
-
s.add_dependency(%q<unicorn>, ["~> 0.
|
46
|
+
s.add_dependency(%q<unicorn>, ["~> 0.97.0"])
|
47
47
|
|
48
48
|
# Unicorn already depends on Rack
|
49
49
|
# s.add_dependency(%q<rack>)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 7 "reload config.ru error with preload_app true"
|
4
|
+
|
5
|
+
t_begin "setup and start" && {
|
6
|
+
rainbows_setup
|
7
|
+
rtmpfiles ru
|
8
|
+
|
9
|
+
cat > $ru <<\EOF
|
10
|
+
use Rack::ContentLength
|
11
|
+
use Rack::ContentType, "text/plain"
|
12
|
+
x = { "hello" => "world" }
|
13
|
+
run lambda { |env| [ 200, {}, [ x.inspect << "\n" ] ] }
|
14
|
+
EOF
|
15
|
+
echo 'preload_app true' >> $unicorn_config
|
16
|
+
rainbows -D -c $unicorn_config $ru
|
17
|
+
rainbows_wait_start
|
18
|
+
}
|
19
|
+
|
20
|
+
t_begin "hit with curl" && {
|
21
|
+
out=$(curl -sSf http://$listen/)
|
22
|
+
test x"$out" = x'{"hello"=>"world"}'
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "introduce syntax error in rackup file" && {
|
26
|
+
echo '...' >> $ru
|
27
|
+
}
|
28
|
+
|
29
|
+
t_begin "reload signal succeeds" && {
|
30
|
+
kill -HUP $rainbows_pid
|
31
|
+
rainbows_wait_start
|
32
|
+
while ! egrep '(done|error) reloading' $r_err >/dev/null
|
33
|
+
do
|
34
|
+
sleep 1
|
35
|
+
done
|
36
|
+
|
37
|
+
grep 'error reloading' $r_err >/dev/null
|
38
|
+
> $r_err
|
39
|
+
}
|
40
|
+
|
41
|
+
t_begin "hit with curl" && {
|
42
|
+
out=$(curl -sSf http://$listen/)
|
43
|
+
test x"$out" = x'{"hello"=>"world"}'
|
44
|
+
}
|
45
|
+
|
46
|
+
t_begin "killing succeeds" && {
|
47
|
+
kill $rainbows_pid
|
48
|
+
}
|
49
|
+
|
50
|
+
t_begin "check stderr" && {
|
51
|
+
check_stderr
|
52
|
+
}
|
53
|
+
|
54
|
+
t_done
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 6 "config variables conflict with preload_app"
|
4
|
+
|
5
|
+
t_begin "setup and start" && {
|
6
|
+
rainbows_setup
|
7
|
+
rtmpfiles ru rutmp
|
8
|
+
|
9
|
+
cat > $ru <<\EOF
|
10
|
+
use Rack::ContentLength
|
11
|
+
use Rack::ContentType, "text/plain"
|
12
|
+
config = ru = { "hello" => "world" }
|
13
|
+
run lambda { |env| [ 200, {}, [ ru.inspect << "\n" ] ] }
|
14
|
+
EOF
|
15
|
+
echo 'preload_app true' >> $unicorn_config
|
16
|
+
rainbows -D -c $unicorn_config $ru
|
17
|
+
rainbows_wait_start
|
18
|
+
}
|
19
|
+
|
20
|
+
t_begin "hit with curl" && {
|
21
|
+
out=$(curl -sSf http://$listen/)
|
22
|
+
test x"$out" = x'{"hello"=>"world"}'
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "modify rackup file" && {
|
26
|
+
sed -e 's/world/WORLD/' < $ru > $rutmp
|
27
|
+
mv $rutmp $ru
|
28
|
+
}
|
29
|
+
|
30
|
+
t_begin "reload signal succeeds" && {
|
31
|
+
kill -HUP $rainbows_pid
|
32
|
+
rainbows_wait_start
|
33
|
+
while ! egrep '(done|error) reloading' < $r_err >/dev/null
|
34
|
+
do
|
35
|
+
sleep 1
|
36
|
+
done
|
37
|
+
|
38
|
+
grep 'done reloading' $r_err >/dev/null
|
39
|
+
}
|
40
|
+
|
41
|
+
t_begin "hit with curl" && {
|
42
|
+
out=$(curl -sSf http://$listen/)
|
43
|
+
test x"$out" = x'{"hello"=>"WORLD"}'
|
44
|
+
}
|
45
|
+
|
46
|
+
t_begin "killing succeeds" && {
|
47
|
+
kill $rainbows_pid
|
48
|
+
}
|
49
|
+
|
50
|
+
t_done
|
data/t/test-lib.sh
CHANGED
@@ -99,13 +99,7 @@ pid "$pid"
|
|
99
99
|
stderr_path "$r_err"
|
100
100
|
stdout_path "$r_out"
|
101
101
|
|
102
|
-
|
103
|
-
unless ENV['UNICORN_FD']
|
104
|
-
IO.for_fd(3).close rescue nil
|
105
|
-
IO.for_fd(4).close rescue nil
|
106
|
-
end
|
107
|
-
|
108
|
-
before_fork do |server, worker|
|
102
|
+
after_fork do |server, worker|
|
109
103
|
# test script will block while reading from $fifo,
|
110
104
|
# so notify the script on the first worker we spawn
|
111
105
|
# by opening the FIFO
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rainbows
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.91.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rainbows! hackers
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-03-01 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -19,9 +19,6 @@ dependencies:
|
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.96.1
|
24
|
-
- - <
|
25
22
|
- !ruby/object:Gem::Version
|
26
23
|
version: 0.97.0
|
27
24
|
version:
|
@@ -202,6 +199,8 @@ files:
|
|
202
199
|
- t/t0010-keepalive-timeout-effective.sh
|
203
200
|
- t/t0011-close-on-exec-set.sh
|
204
201
|
- t/t0012-spurious-wakeups-quiet.sh
|
202
|
+
- t/t0013-reload-bad-config.sh
|
203
|
+
- t/t0014-config-conflict.sh
|
205
204
|
- t/t0100-rack-input-hammer.sh
|
206
205
|
- t/t0101-rack-input-trailer.sh
|
207
206
|
- t/t0102-rack-input-short.sh
|