rainbows 0.90.2 → 0.91.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|