unicorn 0.8.2 → 0.8.3
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/CHANGELOG +1 -0
- data/GNUmakefile +4 -4
- data/lib/unicorn.rb +10 -13
- data/lib/unicorn/app/exec_cgi.rb +4 -9
- data/lib/unicorn/const.rb +1 -1
- data/lib/unicorn/util.rb +17 -0
- data/test/unit/test_util.rb +30 -28
- data/unicorn.gemspec +3 -3
- metadata +8 -8
data/CHANGELOG
CHANGED
data/GNUmakefile
CHANGED
@@ -48,7 +48,7 @@ http11: lib/unicorn/http11.$(DLEXT)
|
|
48
48
|
|
49
49
|
$(test_prefix)/.stamp: $(inst_deps)
|
50
50
|
mkdir -p $(test_prefix)/.ccache
|
51
|
-
tar c
|
51
|
+
tar c `cat Manifest` | (cd $(test_prefix) && tar x)
|
52
52
|
$(MAKE) -C $(test_prefix) clean
|
53
53
|
$(MAKE) -C $(test_prefix) http11 shebang
|
54
54
|
> $@
|
@@ -88,14 +88,14 @@ run_test = $(quiet_pre) setsid $(ruby) -w $(arg) $(TEST_OPTS) $(quiet_post) || \
|
|
88
88
|
%.n: arg = $(subst .n,,$(subst --, -n ,$@))
|
89
89
|
%.n: t = $(subst .n,$(log_suffix),$@)
|
90
90
|
%.n: export PATH := $(test_prefix)/bin:$(PATH)
|
91
|
-
%.n: export RUBYLIB := $(test_prefix)/lib:$(RUBYLIB)
|
91
|
+
%.n: export RUBYLIB := $(test_prefix):$(test_prefix)/lib:$(RUBYLIB)
|
92
92
|
%.n: $(test_prefix)/.stamp
|
93
93
|
$(run_test)
|
94
94
|
|
95
95
|
$(T): arg = $@
|
96
96
|
$(T): t = $(subst .rb,$(log_suffix),$@)
|
97
97
|
$(T): export PATH := $(test_prefix)/bin:$(PATH)
|
98
|
-
$(T): export RUBYLIB := $(test_prefix)/lib:$(RUBYLIB)
|
98
|
+
$(T): export RUBYLIB := $(test_prefix):$(test_prefix)/lib:$(RUBYLIB)
|
99
99
|
$(T): $(test_prefix)/.stamp
|
100
100
|
$(run_test)
|
101
101
|
|
@@ -141,7 +141,7 @@ $(T_r).%.r: rv = $(subst .r,,$(subst $(T_r).,,$@))
|
|
141
141
|
$(T_r).%.r: extra = ' 'v$(rv)
|
142
142
|
$(T_r).%.r: arg = $(T_r)
|
143
143
|
$(T_r).%.r: export PATH := $(test_prefix)/bin:$(PATH)
|
144
|
-
$(T_r).%.r: export RUBYLIB := $(test_prefix)/lib:$(RUBYLIB)
|
144
|
+
$(T_r).%.r: export RUBYLIB := $(test_prefix):$(test_prefix)/lib:$(RUBYLIB)
|
145
145
|
$(T_r).%.r: export UNICORN_RAILS_TEST_VERSION = $(rv)
|
146
146
|
$(T_r).%.r: export RAILS_GIT_REPO = $(CURDIR)/$(rails_git)
|
147
147
|
$(T_r).%.r: $(test_prefix)/.stamp $(rails_git)/info/cloned-stamp
|
data/lib/unicorn.rb
CHANGED
@@ -54,8 +54,7 @@ module Unicorn
|
|
54
54
|
0 => $0.dup,
|
55
55
|
}
|
56
56
|
|
57
|
-
Worker
|
58
|
-
class Worker
|
57
|
+
class Worker < Struct.new(:nr, :tmp)
|
59
58
|
# worker objects may be compared to just plain numbers
|
60
59
|
def ==(other_nr)
|
61
60
|
self.nr == other_nr
|
@@ -323,7 +322,7 @@ module Unicorn
|
|
323
322
|
self.pid = @pid.chomp('.oldbin') if @pid
|
324
323
|
proc_name 'master'
|
325
324
|
else
|
326
|
-
worker = WORKERS.delete(pid) and worker.
|
325
|
+
worker = WORKERS.delete(pid) and worker.tmp.close rescue nil
|
327
326
|
logger.info "reaped #{status.inspect} " \
|
328
327
|
"worker=#{worker.nr rescue 'unknown'}"
|
329
328
|
end
|
@@ -383,16 +382,16 @@ module Unicorn
|
|
383
382
|
end
|
384
383
|
|
385
384
|
# forcibly terminate all workers that haven't checked in in @timeout
|
386
|
-
# seconds. The timeout is implemented using an unlinked
|
385
|
+
# seconds. The timeout is implemented using an unlinked File
|
387
386
|
# shared between the parent process and each worker. The worker
|
388
|
-
# runs File#chmod to modify the ctime of the
|
387
|
+
# runs File#chmod to modify the ctime of the File. If the ctime
|
389
388
|
# is stale for >@timeout seconds, then we'll kill the corresponding
|
390
389
|
# worker.
|
391
390
|
def murder_lazy_workers
|
392
391
|
diff = stat = nil
|
393
392
|
WORKERS.dup.each_pair do |pid, worker|
|
394
393
|
stat = begin
|
395
|
-
worker.
|
394
|
+
worker.tmp.stat
|
396
395
|
rescue => e
|
397
396
|
logger.warn "worker=#{worker.nr} PID:#{pid} stat error: #{e.inspect}"
|
398
397
|
kill_worker(:QUIT, pid)
|
@@ -416,9 +415,7 @@ module Unicorn
|
|
416
415
|
SIG_QUEUE << :QUIT # forcibly emulate SIGQUIT
|
417
416
|
return
|
418
417
|
end
|
419
|
-
|
420
|
-
tempfile.unlink # don't allow other processes to find or see it
|
421
|
-
worker = Worker.new(worker_nr, tempfile)
|
418
|
+
worker = Worker.new(worker_nr, Unicorn::Util.tmpio)
|
422
419
|
@before_fork.call(self, worker)
|
423
420
|
pid = fork { worker_loop(worker) }
|
424
421
|
WORKERS[pid] = worker
|
@@ -466,10 +463,10 @@ module Unicorn
|
|
466
463
|
proc_name "worker[#{worker.nr}]"
|
467
464
|
START_CTX.clear
|
468
465
|
init_self_pipe!
|
469
|
-
WORKERS.values.each { |other| other.
|
466
|
+
WORKERS.values.each { |other| other.tmp.close rescue nil }
|
470
467
|
WORKERS.clear
|
471
468
|
LISTENERS.each { |sock| sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) }
|
472
|
-
worker.
|
469
|
+
worker.tmp.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
473
470
|
@after_fork.call(self, worker) # can drop perms
|
474
471
|
@timeout /= 2.0 # halve it for select()
|
475
472
|
build_app! unless @preload_app
|
@@ -489,7 +486,7 @@ module Unicorn
|
|
489
486
|
master_pid = Process.ppid # slightly racy, but less memory usage
|
490
487
|
init_worker_process(worker)
|
491
488
|
nr = 0 # this becomes negative if we need to reopen logs
|
492
|
-
alive = worker.
|
489
|
+
alive = worker.tmp # tmp is our lifeline to the master process
|
493
490
|
ready = LISTENERS
|
494
491
|
t = ti = 0
|
495
492
|
|
@@ -555,7 +552,7 @@ module Unicorn
|
|
555
552
|
begin
|
556
553
|
Process.kill(signal, pid)
|
557
554
|
rescue Errno::ESRCH
|
558
|
-
worker = WORKERS.delete(pid) and worker.
|
555
|
+
worker = WORKERS.delete(pid) and worker.tmp.close rescue nil
|
559
556
|
end
|
560
557
|
end
|
561
558
|
|
data/lib/unicorn/app/exec_cgi.rb
CHANGED
@@ -42,11 +42,8 @@ module Unicorn::App
|
|
42
42
|
|
43
43
|
# Calls the app
|
44
44
|
def call(env)
|
45
|
-
out, err =
|
46
|
-
out.unlink
|
47
|
-
err.unlink
|
45
|
+
out, err = Unicorn::Util.tmpio, Unicorn::Util.tmpio
|
48
46
|
inp = force_file_input(env)
|
49
|
-
inp.sync = out.sync = err.sync = true
|
50
47
|
pid = fork { run_child(inp, out, err, env) }
|
51
48
|
inp.close
|
52
49
|
pid, status = Process.waitpid2(pid)
|
@@ -124,14 +121,12 @@ module Unicorn::App
|
|
124
121
|
if inp.respond_to?(:fileno) && Integer === inp.fileno
|
125
122
|
inp
|
126
123
|
elsif inp.size == 0 # inp could be a StringIO or StringIO-like object
|
127
|
-
::File.open('/dev/null')
|
124
|
+
::File.open('/dev/null', 'rb')
|
128
125
|
else
|
129
|
-
tmp =
|
130
|
-
tmp.unlink
|
131
|
-
tmp.binmode
|
126
|
+
tmp = Unicorn::Util.tmpio
|
132
127
|
|
133
128
|
# Rack::Lint::InputWrapper doesn't allow sysread :(
|
134
|
-
buf =
|
129
|
+
buf = Unicorn::Z.dup
|
135
130
|
while inp.read(CHUNK_SIZE, buf)
|
136
131
|
tmp.syswrite(buf)
|
137
132
|
end
|
data/lib/unicorn/const.rb
CHANGED
@@ -5,7 +5,7 @@ module Unicorn
|
|
5
5
|
# gave about a 3% to 10% performance improvement over using the strings directly.
|
6
6
|
# Symbols did not really improve things much compared to constants.
|
7
7
|
module Const
|
8
|
-
UNICORN_VERSION="0.8.
|
8
|
+
UNICORN_VERSION="0.8.3".freeze
|
9
9
|
|
10
10
|
DEFAULT_HOST = "0.0.0.0".freeze # default TCP listen host address
|
11
11
|
DEFAULT_PORT = "8080".freeze # default TCP listen port
|
data/lib/unicorn/util.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fcntl'
|
2
|
+
require 'tmpdir'
|
2
3
|
|
3
4
|
module Unicorn
|
4
5
|
class Util
|
@@ -39,6 +40,22 @@ module Unicorn
|
|
39
40
|
nr
|
40
41
|
end
|
41
42
|
|
43
|
+
# creates and returns a new File object. The File is unlinked
|
44
|
+
# immediately, switched to binary mode, and userspace output
|
45
|
+
# buffering is disabled
|
46
|
+
def tmpio
|
47
|
+
fp = begin
|
48
|
+
File.open("#{Dir::tmpdir}/#{rand}",
|
49
|
+
File::RDWR|File::CREAT|File::EXCL, 0600)
|
50
|
+
rescue Errno::EEXIST
|
51
|
+
retry
|
52
|
+
end
|
53
|
+
File.unlink(fp.path)
|
54
|
+
fp.binmode
|
55
|
+
fp.sync = true
|
56
|
+
fp
|
57
|
+
end
|
58
|
+
|
42
59
|
end
|
43
60
|
|
44
61
|
end
|
data/test/unit/test_util.rb
CHANGED
@@ -43,20 +43,21 @@ class TestUtil < Test::Unit::TestCase
|
|
43
43
|
tmp = Tempfile.new(nil)
|
44
44
|
tmp_path = tmp.path.dup.freeze
|
45
45
|
Encoding.list.each { |encoding|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
46
|
+
File.open(tmp_path, "a:#{encoding.to_s}") { |fp|
|
47
|
+
fp.sync = true
|
48
|
+
assert_equal encoding, fp.external_encoding
|
49
|
+
assert_nil fp.internal_encoding
|
50
|
+
File.unlink(tmp_path)
|
51
|
+
assert ! File.exist?(tmp_path)
|
52
|
+
Unicorn::Util.reopen_logs
|
53
|
+
assert_equal tmp_path, fp.path
|
54
|
+
assert File.exist?(tmp_path)
|
55
|
+
assert_equal fp.stat.inspect, File.stat(tmp_path).inspect
|
56
|
+
assert_equal encoding, fp.external_encoding
|
57
|
+
assert_nil fp.internal_encoding
|
58
|
+
assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & fp.fcntl(Fcntl::F_GETFL))
|
59
|
+
assert fp.sync
|
60
|
+
}
|
60
61
|
}
|
61
62
|
end if STDIN.respond_to?(:external_encoding)
|
62
63
|
|
@@ -66,20 +67,21 @@ class TestUtil < Test::Unit::TestCase
|
|
66
67
|
Encoding.list.each { |ext|
|
67
68
|
Encoding.list.each { |int|
|
68
69
|
next if ext == int
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
70
|
+
File.open(tmp_path, "a:#{ext.to_s}:#{int.to_s}") { |fp|
|
71
|
+
fp.sync = true
|
72
|
+
assert_equal ext, fp.external_encoding
|
73
|
+
assert_equal int, fp.internal_encoding
|
74
|
+
File.unlink(tmp_path)
|
75
|
+
assert ! File.exist?(tmp_path)
|
76
|
+
Unicorn::Util.reopen_logs
|
77
|
+
assert_equal tmp_path, fp.path
|
78
|
+
assert File.exist?(tmp_path)
|
79
|
+
assert_equal fp.stat.inspect, File.stat(tmp_path).inspect
|
80
|
+
assert_equal ext, fp.external_encoding
|
81
|
+
assert_equal int, fp.internal_encoding
|
82
|
+
assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & fp.fcntl(Fcntl::F_GETFL))
|
83
|
+
assert fp.sync
|
84
|
+
}
|
83
85
|
}
|
84
86
|
}
|
85
87
|
end if STDIN.respond_to?(:external_encoding)
|
data/unicorn.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{unicorn}
|
5
|
-
s.version = "0.8.
|
5
|
+
s.version = "0.8.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Eric Wong"]
|
9
|
-
s.date = %q{2009-07-
|
9
|
+
s.date = %q{2009-07-19}
|
10
10
|
s.description = %q{Rack HTTP server for Unix, fast clients and nothing else}
|
11
11
|
s.email = %q{normalperson@yhbt.net}
|
12
12
|
s.executables = ["unicorn", "unicorn_rails"]
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.rubyforge_project = %q{unicorn}
|
20
20
|
s.rubygems_version = %q{1.3.4}
|
21
21
|
s.summary = %q{Rack HTTP server for Unix, fast clients and nothing else}
|
22
|
-
s.test_files = ["test/unit/
|
22
|
+
s.test_files = ["test/unit/test_request.rb", "test/unit/test_http_parser.rb", "test/unit/test_server.rb", "test/unit/test_response.rb", "test/unit/test_configurator.rb", "test/unit/test_util.rb", "test/unit/test_upload.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb"]
|
23
23
|
|
24
24
|
if s.respond_to? :specification_version then
|
25
25
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Wong
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-19 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -222,12 +222,12 @@ signing_key:
|
|
222
222
|
specification_version: 3
|
223
223
|
summary: Rack HTTP server for Unix, fast clients and nothing else
|
224
224
|
test_files:
|
225
|
-
- test/unit/test_configurator.rb
|
226
|
-
- test/unit/test_response.rb
|
227
225
|
- test/unit/test_request.rb
|
228
|
-
- test/unit/test_signals.rb
|
229
|
-
- test/unit/test_upload.rb
|
230
226
|
- test/unit/test_http_parser.rb
|
231
|
-
- test/unit/test_socket_helper.rb
|
232
|
-
- test/unit/test_util.rb
|
233
227
|
- test/unit/test_server.rb
|
228
|
+
- test/unit/test_response.rb
|
229
|
+
- test/unit/test_configurator.rb
|
230
|
+
- test/unit/test_util.rb
|
231
|
+
- test/unit/test_upload.rb
|
232
|
+
- test/unit/test_signals.rb
|
233
|
+
- test/unit/test_socket_helper.rb
|