unicorn 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/lib/unicorn.rb +5 -0
- data/lib/unicorn/const.rb +2 -2
- data/lib/unicorn/launcher.rb +1 -5
- data/lib/unicorn/tee_input.rb +4 -3
- data/t/pid.ru +3 -0
- data/t/t0008-back_out_of_upgrade.sh +110 -0
- data/test/exec/test_exec.rb +17 -12
- metadata +6 -4
data/GIT-VERSION-GEN
CHANGED
data/lib/unicorn.rb
CHANGED
@@ -312,6 +312,11 @@ module Unicorn
|
|
312
312
|
if path
|
313
313
|
if x = valid_pid?(path)
|
314
314
|
return path if pid && path == pid && x == $$
|
315
|
+
if x == reexec_pid && pid =~ /\.oldbin\z/
|
316
|
+
logger.warn("will not set pid=#{path} while reexec-ed "\
|
317
|
+
"child is running PID:#{x}")
|
318
|
+
return
|
319
|
+
end
|
315
320
|
raise ArgumentError, "Already running on PID:#{x} " \
|
316
321
|
"(or pid=#{path} is stale)"
|
317
322
|
end
|
data/lib/unicorn/const.rb
CHANGED
@@ -8,8 +8,8 @@ module Unicorn
|
|
8
8
|
# Symbols did not really improve things much compared to constants.
|
9
9
|
module Const
|
10
10
|
|
11
|
-
# The current version of Unicorn, currently 1.0.
|
12
|
-
UNICORN_VERSION="1.0.
|
11
|
+
# The current version of Unicorn, currently 1.0.1
|
12
|
+
UNICORN_VERSION="1.0.1"
|
13
13
|
|
14
14
|
DEFAULT_HOST = "0.0.0.0" # default TCP listen host address
|
15
15
|
DEFAULT_PORT = 8080 # default TCP listen port
|
data/lib/unicorn/launcher.rb
CHANGED
@@ -24,11 +24,7 @@ module Unicorn::Launcher
|
|
24
24
|
|
25
25
|
# We only start a new process group if we're not being reexecuted
|
26
26
|
# and inheriting file descriptors from our parent
|
27
|
-
|
28
|
-
exit if fork
|
29
|
-
Process.setsid
|
30
|
-
exit if fork
|
31
|
-
else
|
27
|
+
unless ENV['UNICORN_FD']
|
32
28
|
# grandparent - reads pipe, exits when master is ready
|
33
29
|
# \_ parent - exits immediately ASAP
|
34
30
|
# \_ unicorn master - writes to pipe when ready
|
data/lib/unicorn/tee_input.rb
CHANGED
@@ -109,7 +109,7 @@ module Unicorn
|
|
109
109
|
# unlike IO#gets.
|
110
110
|
def gets
|
111
111
|
socket or return tmp.gets
|
112
|
-
|
112
|
+
sep = $/ or return read
|
113
113
|
|
114
114
|
orig_size = tmp.size
|
115
115
|
if tmp.pos == orig_size
|
@@ -117,8 +117,9 @@ module Unicorn
|
|
117
117
|
tmp.seek(orig_size)
|
118
118
|
end
|
119
119
|
|
120
|
+
sep_size = Rack::Utils.bytesize(sep)
|
120
121
|
line = tmp.gets # cannot be nil here since size > pos
|
121
|
-
|
122
|
+
sep == line[-sep_size, sep_size] and return line
|
122
123
|
|
123
124
|
# unlikely, if we got here, then tmp is at EOF
|
124
125
|
begin
|
@@ -126,7 +127,7 @@ module Unicorn
|
|
126
127
|
tee(Const::CHUNK_SIZE, buf2) or break
|
127
128
|
tmp.seek(orig_size)
|
128
129
|
line << tmp.gets
|
129
|
-
|
130
|
+
sep == line[-sep_size, sep_size] and return line
|
130
131
|
# tmp is at EOF again here, retry the loop
|
131
132
|
end while true
|
132
133
|
|
data/t/pid.ru
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 13 "backout of USR2 upgrade"
|
4
|
+
|
5
|
+
worker_wait_start () {
|
6
|
+
test xSTART = x"$(cat $fifo)"
|
7
|
+
unicorn_pid=$(cat $pid)
|
8
|
+
}
|
9
|
+
|
10
|
+
t_begin "setup and start" && {
|
11
|
+
unicorn_setup
|
12
|
+
rm -f $pid.oldbin
|
13
|
+
|
14
|
+
cat >> $unicorn_config <<EOF
|
15
|
+
after_fork do |server, worker|
|
16
|
+
# test script will block while reading from $fifo,
|
17
|
+
# so notify the script on the first worker we spawn
|
18
|
+
# by opening the FIFO
|
19
|
+
if worker.nr == 0
|
20
|
+
File.open("$fifo", "wb") { |fp| fp.syswrite "START" }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
EOF
|
24
|
+
unicorn -D -c $unicorn_config pid.ru
|
25
|
+
worker_wait_start
|
26
|
+
orig_master_pid=$unicorn_pid
|
27
|
+
}
|
28
|
+
|
29
|
+
t_begin "read original worker pid" && {
|
30
|
+
orig_worker_pid=$(curl -sSf http://$listen/)
|
31
|
+
test -n "$orig_worker_pid" && kill -0 $orig_worker_pid
|
32
|
+
}
|
33
|
+
|
34
|
+
t_begin "upgrade to new master" && {
|
35
|
+
kill -USR2 $orig_master_pid
|
36
|
+
}
|
37
|
+
|
38
|
+
t_begin "kill old worker" && {
|
39
|
+
kill -WINCH $orig_master_pid
|
40
|
+
}
|
41
|
+
|
42
|
+
t_begin "wait for new worker to start" && {
|
43
|
+
worker_wait_start
|
44
|
+
test $unicorn_pid -ne $orig_master_pid
|
45
|
+
new_master_pid=$unicorn_pid
|
46
|
+
}
|
47
|
+
|
48
|
+
t_begin "old master pid is stashed in $pid.oldbin" && {
|
49
|
+
test -s "$pid.oldbin"
|
50
|
+
test $orig_master_pid -eq $(cat $pid.oldbin)
|
51
|
+
}
|
52
|
+
|
53
|
+
t_begin "ensure old worker is no longer running" && {
|
54
|
+
i=0
|
55
|
+
while kill -0 $orig_worker_pid 2>/dev/null
|
56
|
+
do
|
57
|
+
i=$(( $i + 1 ))
|
58
|
+
test $i -lt 600 || die "timed out"
|
59
|
+
sleep 1
|
60
|
+
done
|
61
|
+
}
|
62
|
+
|
63
|
+
t_begin "capture pid of new worker" && {
|
64
|
+
new_worker_pid=$(curl -sSf http://$listen/)
|
65
|
+
}
|
66
|
+
|
67
|
+
t_begin "reload old master process" && {
|
68
|
+
kill -HUP $orig_master_pid
|
69
|
+
worker_wait_start
|
70
|
+
}
|
71
|
+
|
72
|
+
t_begin "gracefully kill new master and ensure it dies" && {
|
73
|
+
kill -QUIT $new_master_pid
|
74
|
+
i=0
|
75
|
+
while kill -0 $new_worker_pid 2>/dev/null
|
76
|
+
do
|
77
|
+
i=$(( $i + 1 ))
|
78
|
+
test $i -lt 600 || die "timed out"
|
79
|
+
sleep 1
|
80
|
+
done
|
81
|
+
}
|
82
|
+
|
83
|
+
t_begin "ensure $pid.oldbin does not exist" && {
|
84
|
+
i=0
|
85
|
+
while test -s $pid.oldbin
|
86
|
+
do
|
87
|
+
i=$(( $i + 1 ))
|
88
|
+
test $i -lt 600 || die "timed out"
|
89
|
+
sleep 1
|
90
|
+
done
|
91
|
+
while ! test -s $pid
|
92
|
+
do
|
93
|
+
i=$(( $i + 1 ))
|
94
|
+
test $i -lt 600 || die "timed out"
|
95
|
+
sleep 1
|
96
|
+
done
|
97
|
+
}
|
98
|
+
|
99
|
+
t_begin "ensure $pid is correct" && {
|
100
|
+
cur_master_pid=$(cat $pid)
|
101
|
+
test $orig_master_pid -eq $cur_master_pid
|
102
|
+
}
|
103
|
+
|
104
|
+
t_begin "killing succeeds" && {
|
105
|
+
kill $orig_master_pid
|
106
|
+
}
|
107
|
+
|
108
|
+
dbgcat r_err
|
109
|
+
|
110
|
+
t_done
|
data/test/exec/test_exec.rb
CHANGED
@@ -54,6 +54,20 @@ before_fork do |server, worker|
|
|
54
54
|
end
|
55
55
|
EOS
|
56
56
|
|
57
|
+
WORKING_DIRECTORY_CHECK_RU = <<-EOS
|
58
|
+
use Rack::ContentLength
|
59
|
+
run lambda { |env|
|
60
|
+
pwd = ENV['PWD']
|
61
|
+
a = ::File.stat(pwd)
|
62
|
+
b = ::File.stat(Dir.pwd)
|
63
|
+
if (a.ino == b.ino && a.dev == b.dev)
|
64
|
+
[ 200, { 'Content-Type' => 'text/plain' }, [ pwd ] ]
|
65
|
+
else
|
66
|
+
[ 404, { 'Content-Type' => 'text/plain' }, [] ]
|
67
|
+
end
|
68
|
+
}
|
69
|
+
EOS
|
70
|
+
|
57
71
|
def setup
|
58
72
|
@pwd = Dir.pwd
|
59
73
|
@tmpfile = Tempfile.new('unicorn_exec_test')
|
@@ -87,10 +101,7 @@ end
|
|
87
101
|
File.unlink(other.path)
|
88
102
|
Dir.mkdir(other.path)
|
89
103
|
File.open("config.ru", "wb") do |fp|
|
90
|
-
fp.syswrite
|
91
|
-
use Rack::ContentLength
|
92
|
-
run proc { |env| [ 200, { 'Content-Type' => 'text/plain' }, [ Dir.pwd ] ] }
|
93
|
-
EOF
|
104
|
+
fp.syswrite WORKING_DIRECTORY_CHECK_RU
|
94
105
|
end
|
95
106
|
FileUtils.cp("config.ru", other.path + "/config.ru")
|
96
107
|
Dir.chdir(@tmpdir)
|
@@ -138,10 +149,7 @@ EOF
|
|
138
149
|
File.unlink(other.path)
|
139
150
|
Dir.mkdir(other.path)
|
140
151
|
File.open("config.ru", "wb") do |fp|
|
141
|
-
fp.syswrite
|
142
|
-
use Rack::ContentLength
|
143
|
-
run proc { |env| [ 200, { 'Content-Type' => 'text/plain' }, [ Dir.pwd ] ] }
|
144
|
-
EOF
|
152
|
+
fp.syswrite WORKING_DIRECTORY_CHECK_RU
|
145
153
|
end
|
146
154
|
FileUtils.cp("config.ru", other.path + "/config.ru")
|
147
155
|
tmp = Tempfile.new('unicorn.config')
|
@@ -177,10 +185,7 @@ EOF
|
|
177
185
|
File.unlink(other.path)
|
178
186
|
Dir.mkdir(other.path)
|
179
187
|
File.open("config.ru", "wb") do |fp|
|
180
|
-
fp.syswrite
|
181
|
-
use Rack::ContentLength
|
182
|
-
run proc { |env| [ 200, { 'Content-Type' => 'text/plain' }, [ Dir.pwd ] ] }
|
183
|
-
EOF
|
188
|
+
fp.syswrite WORKING_DIRECTORY_CHECK_RU
|
184
189
|
end
|
185
190
|
FileUtils.cp("config.ru", other.path + "/config.ru")
|
186
191
|
system('mkfifo', "#{other.path}/fifo")
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Unicorn hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-07-13 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- t/bin/utee
|
170
170
|
- t/env.ru
|
171
171
|
- t/my-tap-lib.sh
|
172
|
+
- t/pid.ru
|
172
173
|
- t/rails3-app/.gitignore
|
173
174
|
- t/rails3-app/Gemfile
|
174
175
|
- t/rails3-app/Rakefile
|
@@ -209,6 +210,7 @@ files:
|
|
209
210
|
- t/t0006-reopen-logs.sh
|
210
211
|
- t/t0006.ru
|
211
212
|
- t/t0007-working_directory_no_embed_cli.sh
|
213
|
+
- t/t0008-back_out_of_upgrade.sh
|
212
214
|
- t/t0300-rails3-basic.sh
|
213
215
|
- t/t0301-rails3-missing-config-ru.sh
|
214
216
|
- t/t0302-rails3-alt-working_directory.sh
|