unicorn 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/CHANGELOG +1 -0
- data/GNUmakefile +4 -2
- data/Manifest +3 -0
- data/README +2 -2
- data/TODO +0 -2
- data/TUNING +63 -0
- data/examples/init.sh +54 -0
- data/lib/unicorn.rb +3 -3
- data/lib/unicorn/app/exec_cgi.rb +3 -3
- data/lib/unicorn/app/old_rails.rb +2 -2
- data/lib/unicorn/configurator.rb +24 -22
- data/lib/unicorn/const.rb +1 -1
- data/lib/unicorn/http_response.rb +1 -1
- data/lib/unicorn/util.rb +10 -5
- data/test/unit/test_request.rb +0 -5
- data/test/unit/test_response.rb +9 -1
- data/test/unit/test_upload.rb +18 -0
- data/test/unit/test_util.rb +87 -0
- data/unicorn.gemspec +6 -6
- metadata +15 -9
data/.document
CHANGED
data/CHANGELOG
CHANGED
data/GNUmakefile
CHANGED
@@ -53,8 +53,10 @@ $(test_prefix)/.stamp: $(inst_deps)
|
|
53
53
|
$(MAKE) -C $(test_prefix) http11 shebang
|
54
54
|
> $@
|
55
55
|
|
56
|
+
bins := $(wildcard bin/*)
|
57
|
+
|
56
58
|
# this is only intended to be run within $(test_prefix)
|
57
|
-
shebang:
|
59
|
+
shebang: $(bins)
|
58
60
|
$(ruby) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $^
|
59
61
|
|
60
62
|
t_log := $(T_log) $(T_n_log)
|
@@ -97,7 +99,7 @@ $(T): export RUBYLIB := $(test_prefix)/lib:$(RUBYLIB)
|
|
97
99
|
$(T): $(test_prefix)/.stamp
|
98
100
|
$(run_test)
|
99
101
|
|
100
|
-
install:
|
102
|
+
install: $(bins)
|
101
103
|
$(prep_setup_rb)
|
102
104
|
$(RM) -r .install-tmp
|
103
105
|
mkdir .install-tmp
|
data/Manifest
CHANGED
@@ -11,8 +11,10 @@ README
|
|
11
11
|
Rakefile
|
12
12
|
SIGNALS
|
13
13
|
TODO
|
14
|
+
TUNING
|
14
15
|
bin/unicorn
|
15
16
|
bin/unicorn_rails
|
17
|
+
examples/init.sh
|
16
18
|
ext/unicorn/http11/ext_help.h
|
17
19
|
ext/unicorn/http11/extconf.rb
|
18
20
|
ext/unicorn/http11/http11.c
|
@@ -127,3 +129,4 @@ test/unit/test_server.rb
|
|
127
129
|
test/unit/test_signals.rb
|
128
130
|
test/unit/test_socket_helper.rb
|
129
131
|
test/unit/test_upload.rb
|
132
|
+
test/unit/test_util.rb
|
data/README
CHANGED
@@ -103,7 +103,7 @@ In RAILS_ROOT, run:
|
|
103
103
|
unicorn_rails
|
104
104
|
|
105
105
|
Unicorn will bind to all interfaces TCP port 8080 by default.
|
106
|
-
You may use the
|
106
|
+
You may use the +-l/--listen+ switch to bind to a different
|
107
107
|
address:port or a UNIX socket.
|
108
108
|
|
109
109
|
=== Configuration File(s)
|
@@ -111,7 +111,7 @@ address:port or a UNIX socket.
|
|
111
111
|
Unicorn will look for the config.ru file used by rackup in APP_ROOT.
|
112
112
|
|
113
113
|
For deployments, it can use a config file for Unicorn-specific options
|
114
|
-
specified by the
|
114
|
+
specified by the +--config-file/-c+ command-line switch. See
|
115
115
|
Unicorn::Configurator for the syntax of the Unicorn-specific options.
|
116
116
|
The default settings are designed for maximum out-of-the-box
|
117
117
|
compatibility with existing applications.
|
data/TODO
CHANGED
data/TUNING
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
= Tuning Unicorn
|
2
|
+
|
3
|
+
Unicorn performance is generally as good as a (mostly) Ruby web server
|
4
|
+
can provide. Most often the performance bottleneck is in the web
|
5
|
+
application running on Unicorn rather than Unicorn itself.
|
6
|
+
|
7
|
+
== Unicorn Configuration
|
8
|
+
|
9
|
+
See Unicorn::Configurator for details on the config file format.
|
10
|
+
|
11
|
+
* Setting a very low value for the :backlog parameter in "listen"
|
12
|
+
directives can allow failover to happen more quickly if your
|
13
|
+
cluster is configured for it.
|
14
|
+
|
15
|
+
* :rcvbuf and :sndbuf parameters generally do not need to be set for TCP
|
16
|
+
listeners under Linux 2.6 because auto-tuning is enabled. UNIX domain
|
17
|
+
sockets do not have auto-tuning buffer sizes; so increasing those will
|
18
|
+
allow syscalls and task switches to be saved for larger requests
|
19
|
+
and responses.
|
20
|
+
|
21
|
+
* Setting "preload_app true" can allow copy-on-write-friendly GC to
|
22
|
+
be used to save memory. It will probably not work out of the box with
|
23
|
+
applications that open sockets or perform random I/O on files.
|
24
|
+
Databases like TokyoCabinet use concurrency-safe pread()/pwrite()
|
25
|
+
functions for safe sharing of database file descriptors across
|
26
|
+
processes.
|
27
|
+
|
28
|
+
* On POSIX-compliant filesystems, it is safe for multiple threads or
|
29
|
+
processes to append to one log file as long as all the processes are
|
30
|
+
have them unbuffered (File#sync = true) or they are
|
31
|
+
record(line)-buffered in userspace.
|
32
|
+
|
33
|
+
* worker_processes should be scaled to the number of processes your
|
34
|
+
backend system(s) can support. DO NOT scale it to the number of
|
35
|
+
external network clients your application expects to be serving.
|
36
|
+
Unicorn is NOT for serving slow clients, that is the job of nginx.
|
37
|
+
|
38
|
+
== Kernel Parameters (Linux sysctl)
|
39
|
+
|
40
|
+
WARNING: Do not change system parameters unless you know what you're doing!
|
41
|
+
|
42
|
+
* net.core.rmem_max and net.core.wmem_max can increase the allowed
|
43
|
+
size of :rcvbuf and :sndbuf respectively. This is mostly only useful
|
44
|
+
for UNIX domain sockets which do not have auto-tuning buffer sizes.
|
45
|
+
|
46
|
+
* For load testing/benchmarking with UNIX domain sockets, you should
|
47
|
+
consider increasing net.core.somaxconn or else nginx will start
|
48
|
+
failing to connect under heavy load.
|
49
|
+
|
50
|
+
* If you're running out of local ports, consider lowering
|
51
|
+
net.ipv4.tcp_fin_timeout to 20-30 (default: 60 seconds). Also
|
52
|
+
consider widening the usable port range by changing
|
53
|
+
net.ipv4.ip_local_port_range.
|
54
|
+
|
55
|
+
* Setting net.ipv4.tcp_timestamps=1 will also allow setting
|
56
|
+
net.ipv4.tcp_tw_reuse=1 and net.ipv4.tcp_tw_recycle=1, which along
|
57
|
+
with the above settings can slow down port exhaustion. Not all
|
58
|
+
networks are compatible with these settings, check with your friendly
|
59
|
+
network administrator before changing these.
|
60
|
+
|
61
|
+
* Increasing the MTU size can reduce framing overhead for larger
|
62
|
+
transfers. One often-overlooked detail is that the loopback
|
63
|
+
device (usually "lo") can have its MTU increased, too.
|
data/examples/init.sh
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
set -u
|
3
|
+
set -e
|
4
|
+
# Example init script, this can be used with nginx, too,
|
5
|
+
# since nginx and unicorn accept the same signals
|
6
|
+
|
7
|
+
# Feel free to change any of the following variables for your app:
|
8
|
+
APP_ROOT=/home/x/my_app/current
|
9
|
+
PID=$APP_ROOT/tmp/pids/unicorn.pid
|
10
|
+
CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
|
11
|
+
INIT_CONF=$APP_ROOT/config/init.conf
|
12
|
+
|
13
|
+
test -f "$INIT_CONF" && . $INIT_CONF
|
14
|
+
|
15
|
+
old_pid="$PID.oldbin"
|
16
|
+
|
17
|
+
cd $APP_ROOT || exit 1
|
18
|
+
|
19
|
+
sig () {
|
20
|
+
test -s "$PID" && kill -$1 `cat $PID`
|
21
|
+
}
|
22
|
+
|
23
|
+
oldsig () {
|
24
|
+
test -s $old_pid && kill -$1 `cat $old_pid`
|
25
|
+
}
|
26
|
+
|
27
|
+
case $1 in
|
28
|
+
start)
|
29
|
+
sig 0 && echo >&2 "Already running" && exit 0
|
30
|
+
$CMD
|
31
|
+
;;
|
32
|
+
stop)
|
33
|
+
sig QUIT && exit 0
|
34
|
+
echo >&2 "Not running"
|
35
|
+
;;
|
36
|
+
force-stop)
|
37
|
+
sig TERM && exit 0
|
38
|
+
echo >&2 "Not running"
|
39
|
+
;;
|
40
|
+
restart|reload)
|
41
|
+
sig HUP && echo reloaded OK && exit 0
|
42
|
+
echo >&2 "Couldn't reload, starting '$CMD' instead"
|
43
|
+
$CMD
|
44
|
+
;;
|
45
|
+
upgrade)
|
46
|
+
sig USR2 && sleep 2 && sig 0 && oldsig QUIT && exit 0
|
47
|
+
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
|
48
|
+
$CMD
|
49
|
+
;;
|
50
|
+
*)
|
51
|
+
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop>"
|
52
|
+
exit 1
|
53
|
+
;;
|
54
|
+
esac
|
data/lib/unicorn.rb
CHANGED
@@ -64,6 +64,7 @@ module Unicorn
|
|
64
64
|
# incoming requests on the socket.
|
65
65
|
def initialize(app, options = {})
|
66
66
|
@app = app
|
67
|
+
@pid = nil
|
67
68
|
@reexec_pid = 0
|
68
69
|
@init_listeners = options[:listeners] ? options[:listeners].dup : []
|
69
70
|
@config = Configurator.new(options.merge(:use_defaults => true))
|
@@ -375,9 +376,8 @@ module Unicorn
|
|
375
376
|
# is stale for >@timeout seconds, then we'll kill the corresponding
|
376
377
|
# worker.
|
377
378
|
def murder_lazy_workers
|
378
|
-
now = Time.now
|
379
379
|
WORKERS.each_pair do |pid, worker|
|
380
|
-
|
380
|
+
Time.now - worker.tempfile.ctime <= @timeout and next
|
381
381
|
logger.error "worker=#{worker.nr} PID:#{pid} is too old, killing"
|
382
382
|
kill_worker(:KILL, pid) # take no prisoners for @timeout violations
|
383
383
|
worker.tempfile.close rescue nil
|
@@ -444,7 +444,7 @@ module Unicorn
|
|
444
444
|
# traps for USR1, USR2, and HUP may be set in the @after_fork Proc
|
445
445
|
# by the user.
|
446
446
|
def init_worker_process(worker)
|
447
|
-
QUEUE_SIGS.each { |sig| trap(sig, '
|
447
|
+
QUEUE_SIGS.each { |sig| trap(sig, 'IGNORE') }
|
448
448
|
trap(:CHLD, 'DEFAULT')
|
449
449
|
SIG_QUEUE.clear
|
450
450
|
proc_name "worker[#{worker.nr}]"
|
data/lib/unicorn/app/exec_cgi.rb
CHANGED
@@ -69,9 +69,9 @@ module Unicorn::App
|
|
69
69
|
ENV['GATEWAY_INTERFACE'] = 'CGI/1.1'
|
70
70
|
env.keys.grep(/^HTTP_/) { |key| ENV[key] = env[key] }
|
71
71
|
|
72
|
-
IO.new(0).reopen(inp)
|
73
|
-
IO.new(1).reopen(out)
|
74
|
-
IO.new(2).reopen(err)
|
72
|
+
a = IO.new(0).reopen(inp)
|
73
|
+
b = IO.new(1).reopen(out)
|
74
|
+
c = IO.new(2).reopen(err)
|
75
75
|
exec(*@args)
|
76
76
|
end
|
77
77
|
|
@@ -19,8 +19,8 @@ class Unicorn::App::OldRails
|
|
19
19
|
cgi.body)
|
20
20
|
rescue Object => e
|
21
21
|
err = env['rack.errors']
|
22
|
-
|
23
|
-
e.backtrace.each { |line|
|
22
|
+
err.write("#{e} #{e.message}\n")
|
23
|
+
e.backtrace.each { |line| err.write("#{line}\n") }
|
24
24
|
end
|
25
25
|
cgi.out # finalize the response
|
26
26
|
cgi.rack_response
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -143,12 +143,14 @@ module Unicorn
|
|
143
143
|
# handling the request/app.call/response cycle taking longer than
|
144
144
|
# this time period will be forcibly killed (via SIGKILL). This
|
145
145
|
# timeout is enforced by the master process itself and not subject
|
146
|
-
# to the scheduling limitations by the worker process.
|
146
|
+
# to the scheduling limitations by the worker process. Due the
|
147
|
+
# low-complexity, low-overhead implementation, timeouts of less
|
148
|
+
# than 3.0 seconds can be considered inaccurate and unsafe.
|
147
149
|
def timeout(seconds)
|
148
150
|
Numeric === seconds or raise ArgumentError,
|
149
151
|
"not numeric: timeout=#{seconds.inspect}"
|
150
|
-
seconds
|
151
|
-
"
|
152
|
+
seconds >= 3 or raise ArgumentError,
|
153
|
+
"too low: timeout=#{seconds.inspect}"
|
152
154
|
@set[:timeout] = seconds
|
153
155
|
end
|
154
156
|
|
@@ -179,32 +181,32 @@ module Unicorn
|
|
179
181
|
#
|
180
182
|
# +backlog+: this is the backlog of the listen() syscall.
|
181
183
|
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
184
|
+
# Some operating systems allow negative values here to specify the
|
185
|
+
# maximum allowable value. In most cases, this number is only
|
186
|
+
# recommendation and there are other OS-specific tunables and
|
187
|
+
# variables that can affect this number. See the listen(2)
|
188
|
+
# syscall documentation of your OS for the exact semantics of
|
189
|
+
# this.
|
188
190
|
#
|
189
|
-
#
|
190
|
-
#
|
191
|
-
#
|
191
|
+
# If you are running unicorn on multiple machines, lowering this number
|
192
|
+
# can help your load balancer detect when a machine is overloaded
|
193
|
+
# and give requests to a different machine.
|
192
194
|
#
|
193
|
-
#
|
195
|
+
# Default: 1024
|
194
196
|
#
|
195
197
|
# +rcvbuf+, +sndbuf+: maximum send and receive buffer sizes of sockets
|
196
198
|
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
199
|
+
# These correspond to the SO_RCVBUF and SO_SNDBUF settings which
|
200
|
+
# can be set via the setsockopt(2) syscall. Some kernels
|
201
|
+
# (e.g. Linux 2.4+) have intelligent auto-tuning mechanisms and
|
202
|
+
# there is no need (and it is sometimes detrimental) to specify them.
|
201
203
|
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
204
|
+
# See the socket API documentation of your operating system
|
205
|
+
# to determine the exact semantics of these settings and
|
206
|
+
# other operating system-specific knobs where they can be
|
207
|
+
# specified.
|
206
208
|
#
|
207
|
-
#
|
209
|
+
# Defaults: operating system defaults
|
208
210
|
def listen(address, opt = { :backlog => 1024 })
|
209
211
|
address = expand_addr(address)
|
210
212
|
if String === address
|
data/lib/unicorn/const.rb
CHANGED
@@ -59,7 +59,7 @@ module Unicorn
|
|
59
59
|
REQUEST_URI='REQUEST_URI'.freeze
|
60
60
|
REQUEST_PATH='REQUEST_PATH'.freeze
|
61
61
|
|
62
|
-
UNICORN_VERSION="0.7.
|
62
|
+
UNICORN_VERSION="0.7.1".freeze
|
63
63
|
|
64
64
|
DEFAULT_HOST = "0.0.0.0".freeze # default TCP listen host address
|
65
65
|
DEFAULT_PORT = "8080".freeze # default TCP listen port
|
@@ -31,7 +31,7 @@ module Unicorn
|
|
31
31
|
# writes the rack_response to socket as an HTTP response
|
32
32
|
def self.write(socket, rack_response)
|
33
33
|
status, headers, body = rack_response
|
34
|
-
status = HTTP_STATUS_CODES[status]
|
34
|
+
status = HTTP_STATUS_CODES[status.to_i]
|
35
35
|
OUT.clear
|
36
36
|
|
37
37
|
# Don't bother enforcing duplicate supression, it's a Hash most of
|
data/lib/unicorn/util.rb
CHANGED
@@ -4,6 +4,8 @@ module Unicorn
|
|
4
4
|
class Util
|
5
5
|
class << self
|
6
6
|
|
7
|
+
APPEND_FLAGS = File::WRONLY | File::APPEND
|
8
|
+
|
7
9
|
# this reopens logs that have been rotated (using logrotate(8) or
|
8
10
|
# similar). It is recommended that you install
|
9
11
|
# A +File+ object is considered for reopening if it is:
|
@@ -17,17 +19,20 @@ module Unicorn
|
|
17
19
|
ObjectSpace.each_object(File) do |fp|
|
18
20
|
next if fp.closed?
|
19
21
|
next unless (fp.sync && fp.path[0..0] == "/")
|
20
|
-
|
21
|
-
flags = fp.fcntl(Fcntl::F_GETFL)
|
22
|
-
open_flags = File::WRONLY | File::APPEND
|
23
|
-
next unless (flags & open_flags) == open_flags
|
22
|
+
next unless (fp.fcntl(Fcntl::F_GETFL) & APPEND_FLAGS) == APPEND_FLAGS
|
24
23
|
|
25
24
|
begin
|
26
25
|
a, b = fp.stat, File.stat(fp.path)
|
27
26
|
next if a.ino == b.ino && a.dev == b.dev
|
28
27
|
rescue Errno::ENOENT
|
29
28
|
end
|
30
|
-
|
29
|
+
|
30
|
+
open_arg = 'a'
|
31
|
+
if fp.respond_to?(:external_encoding) && enc = fp.external_encoding
|
32
|
+
open_arg << ":#{enc.to_s}"
|
33
|
+
enc = fp.internal_encoding and open_arg << ":#{enc.to_s}"
|
34
|
+
end
|
35
|
+
fp.reopen(fp.path, open_arg)
|
31
36
|
fp.sync = true
|
32
37
|
nr += 1
|
33
38
|
end # each_object
|
data/test/unit/test_request.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
# Copyright (c) 2009 Eric Wong
|
2
2
|
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
3
|
|
4
|
-
if RUBY_VERSION =~ /1\.9/
|
5
|
-
warn "#$0 current broken under Ruby 1.9 with Rack"
|
6
|
-
exit 0
|
7
|
-
end
|
8
|
-
|
9
4
|
require 'test/test_helper'
|
10
5
|
begin
|
11
6
|
require 'rack'
|
data/test/unit/test_response.rb
CHANGED
@@ -18,11 +18,19 @@ class ResponseTest < Test::Unit::TestCase
|
|
18
18
|
assert out.length > 0, "output didn't have data"
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_response_string_status
|
22
|
+
out = StringIO.new
|
23
|
+
HttpResponse.write(out,['200', {}, []])
|
24
|
+
assert out.closed?
|
25
|
+
assert out.length > 0, "output didn't have data"
|
26
|
+
assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/).size
|
27
|
+
end
|
28
|
+
|
21
29
|
def test_response_OFS_set
|
22
30
|
old_ofs = $,
|
23
31
|
$, = "\f\v"
|
24
32
|
out = StringIO.new
|
25
|
-
HttpResponse.write(out,[200, {"X-
|
33
|
+
HttpResponse.write(out,[200, {"X-k" => "cd","X-y" => "z"}, ["cool"]])
|
26
34
|
assert out.closed?
|
27
35
|
resp = out.string
|
28
36
|
assert ! resp.include?("\f\v"), "output didn't use $, ($OFS)"
|
data/test/unit/test_upload.rb
CHANGED
@@ -19,12 +19,28 @@ class UploadTest < Test::Unit::TestCase
|
|
19
19
|
@sha1_app = lambda do |env|
|
20
20
|
input = env['rack.input']
|
21
21
|
resp = { :pos => input.pos, :size => input.size, :class => input.class }
|
22
|
+
|
23
|
+
# sysread
|
22
24
|
@sha1.reset
|
23
25
|
begin
|
24
26
|
loop { @sha1.update(input.sysread(@bs)) }
|
25
27
|
rescue EOFError
|
26
28
|
end
|
27
29
|
resp[:sha1] = @sha1.hexdigest
|
30
|
+
|
31
|
+
# read
|
32
|
+
input.sysseek(0) if input.respond_to?(:sysseek)
|
33
|
+
input.rewind
|
34
|
+
@sha1.reset
|
35
|
+
loop {
|
36
|
+
buf = input.read(@bs) or break
|
37
|
+
@sha1.update(buf)
|
38
|
+
}
|
39
|
+
|
40
|
+
if resp[:sha1] == @sha1.hexdigest
|
41
|
+
resp[:sysread_read_byte_match] = true
|
42
|
+
end
|
43
|
+
|
28
44
|
[ 200, @hdr.merge({'X-Resp' => resp.inspect}), [] ]
|
29
45
|
end
|
30
46
|
end
|
@@ -218,6 +234,7 @@ class UploadTest < Test::Unit::TestCase
|
|
218
234
|
assert $?.success?, 'curl ran OK'
|
219
235
|
assert_match(%r!\b#{sha1}\b!, resp)
|
220
236
|
assert_match(/Tempfile/, resp)
|
237
|
+
assert_match(/sysread_read_byte_match/, resp)
|
221
238
|
|
222
239
|
# small StringIO path
|
223
240
|
assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
|
@@ -233,6 +250,7 @@ class UploadTest < Test::Unit::TestCase
|
|
233
250
|
assert $?.success?, 'curl ran OK'
|
234
251
|
assert_match(%r!\b#{sha1}\b!, resp)
|
235
252
|
assert_match(/StringIO/, resp)
|
253
|
+
assert_match(/sysread_read_byte_match/, resp)
|
236
254
|
end
|
237
255
|
|
238
256
|
private
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
class TestUtil < Test::Unit::TestCase
|
5
|
+
|
6
|
+
EXPECT_FLAGS = File::WRONLY | File::APPEND
|
7
|
+
def test_reopen_logs_noop
|
8
|
+
tmp = Tempfile.new(nil)
|
9
|
+
tmp.reopen(tmp.path, 'a')
|
10
|
+
tmp.sync = true
|
11
|
+
ext = tmp.external_encoding rescue nil
|
12
|
+
int = tmp.internal_encoding rescue nil
|
13
|
+
before = tmp.stat.inspect
|
14
|
+
Unicorn::Util.reopen_logs
|
15
|
+
assert_equal before, File.stat(tmp.path).inspect
|
16
|
+
assert_equal ext, (tmp.external_encoding rescue nil)
|
17
|
+
assert_equal int, (tmp.internal_encoding rescue nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_reopen_logs_renamed
|
21
|
+
tmp = Tempfile.new(nil)
|
22
|
+
tmp_path = tmp.path.freeze
|
23
|
+
tmp.reopen(tmp_path, 'a')
|
24
|
+
tmp.sync = true
|
25
|
+
ext = tmp.external_encoding rescue nil
|
26
|
+
int = tmp.internal_encoding rescue nil
|
27
|
+
before = tmp.stat.inspect
|
28
|
+
to = Tempfile.new(nil)
|
29
|
+
File.rename(tmp_path, to.path)
|
30
|
+
assert ! File.exist?(tmp_path)
|
31
|
+
Unicorn::Util.reopen_logs
|
32
|
+
assert_equal tmp_path, tmp.path
|
33
|
+
assert File.exist?(tmp_path)
|
34
|
+
assert before != File.stat(tmp_path).inspect
|
35
|
+
assert_equal tmp.stat.inspect, File.stat(tmp_path).inspect
|
36
|
+
assert_equal ext, (tmp.external_encoding rescue nil)
|
37
|
+
assert_equal int, (tmp.internal_encoding rescue nil)
|
38
|
+
assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & tmp.fcntl(Fcntl::F_GETFL))
|
39
|
+
assert tmp.sync
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_reopen_logs_renamed_with_encoding
|
43
|
+
tmp = Tempfile.new(nil)
|
44
|
+
tmp_path = tmp.path.dup.freeze
|
45
|
+
Encoding.list.each { |encoding|
|
46
|
+
tmp.reopen(tmp_path, "a:#{encoding.to_s}")
|
47
|
+
tmp.sync = true
|
48
|
+
assert_equal encoding, tmp.external_encoding
|
49
|
+
assert_nil tmp.internal_encoding
|
50
|
+
File.unlink(tmp_path)
|
51
|
+
assert ! File.exist?(tmp_path)
|
52
|
+
Unicorn::Util.reopen_logs
|
53
|
+
assert_equal tmp_path, tmp.path
|
54
|
+
assert File.exist?(tmp_path)
|
55
|
+
assert_equal tmp.stat.inspect, File.stat(tmp_path).inspect
|
56
|
+
assert_equal encoding, tmp.external_encoding
|
57
|
+
assert_nil tmp.internal_encoding
|
58
|
+
assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & tmp.fcntl(Fcntl::F_GETFL))
|
59
|
+
assert tmp.sync
|
60
|
+
}
|
61
|
+
end if STDIN.respond_to?(:external_encoding)
|
62
|
+
|
63
|
+
def test_reopen_logs_renamed_with_internal_encoding
|
64
|
+
tmp = Tempfile.new(nil)
|
65
|
+
tmp_path = tmp.path.dup.freeze
|
66
|
+
Encoding.list.each { |ext|
|
67
|
+
Encoding.list.each { |int|
|
68
|
+
next if ext == int
|
69
|
+
tmp.reopen(tmp_path, "a:#{ext.to_s}:#{int.to_s}")
|
70
|
+
tmp.sync = true
|
71
|
+
assert_equal ext, tmp.external_encoding
|
72
|
+
assert_equal int, tmp.internal_encoding
|
73
|
+
File.unlink(tmp_path)
|
74
|
+
assert ! File.exist?(tmp_path)
|
75
|
+
Unicorn::Util.reopen_logs
|
76
|
+
assert_equal tmp_path, tmp.path
|
77
|
+
assert File.exist?(tmp_path)
|
78
|
+
assert_equal tmp.stat.inspect, File.stat(tmp_path).inspect
|
79
|
+
assert_equal ext, tmp.external_encoding
|
80
|
+
assert_equal int, tmp.internal_encoding
|
81
|
+
assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & tmp.fcntl(Fcntl::F_GETFL))
|
82
|
+
assert tmp.sync
|
83
|
+
}
|
84
|
+
}
|
85
|
+
end if STDIN.respond_to?(:external_encoding)
|
86
|
+
|
87
|
+
end
|
data/unicorn.gemspec
CHANGED
@@ -2,29 +2,29 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{unicorn}
|
5
|
-
s.version = "0.7.
|
5
|
+
s.version = "0.7.1"
|
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-
|
9
|
+
s.date = %q{2009-05-22}
|
10
10
|
s.description = %q{A small fast HTTP library and server for Rack applications.}
|
11
11
|
s.email = %q{normalperson@yhbt.net}
|
12
12
|
s.executables = ["unicorn", "unicorn_rails"]
|
13
13
|
s.extensions = ["ext/unicorn/http11/extconf.rb"]
|
14
14
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "TODO", "bin/unicorn", "bin/unicorn_rails", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb"]
|
15
|
-
s.files = [".document", ".gitignore", "CHANGELOG", "CONTRIBUTORS", "DESIGN", "GNUmakefile", "LICENSE", "Manifest", "PHILOSOPHY", "README", "Rakefile", "SIGNALS", "TODO", "bin/unicorn", "bin/unicorn_rails", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb", "local.mk.sample", "setup.rb", "test/aggregate.rb", "test/benchmark/README", "test/benchmark/big_request.rb", "test/benchmark/dd.ru", "test/benchmark/request.rb", "test/benchmark/response.rb", "test/exec/README", "test/exec/test_exec.rb", "test/rails/app-1.2.3/.gitignore", "test/rails/app-1.2.3/Rakefile", "test/rails/app-1.2.3/app/controllers/application.rb", "test/rails/app-1.2.3/app/controllers/foo_controller.rb", "test/rails/app-1.2.3/app/helpers/application_helper.rb", "test/rails/app-1.2.3/config/boot.rb", "test/rails/app-1.2.3/config/database.yml", "test/rails/app-1.2.3/config/environment.rb", "test/rails/app-1.2.3/config/environments/development.rb", "test/rails/app-1.2.3/config/environments/production.rb", "test/rails/app-1.2.3/config/routes.rb", "test/rails/app-1.2.3/db/.gitignore", "test/rails/app-1.2.3/log/.gitignore", "test/rails/app-1.2.3/public/404.html", "test/rails/app-1.2.3/public/500.html", "test/rails/app-2.0.2/.gitignore", "test/rails/app-2.0.2/Rakefile", "test/rails/app-2.0.2/app/controllers/application.rb", "test/rails/app-2.0.2/app/controllers/foo_controller.rb", "test/rails/app-2.0.2/app/helpers/application_helper.rb", "test/rails/app-2.0.2/config/boot.rb", "test/rails/app-2.0.2/config/database.yml", "test/rails/app-2.0.2/config/environment.rb", "test/rails/app-2.0.2/config/environments/development.rb", "test/rails/app-2.0.2/config/environments/production.rb", "test/rails/app-2.0.2/config/routes.rb", "test/rails/app-2.0.2/db/.gitignore", "test/rails/app-2.0.2/log/.gitignore", "test/rails/app-2.0.2/public/404.html", "test/rails/app-2.0.2/public/500.html", "test/rails/app-2.1.2/.gitignore", "test/rails/app-2.1.2/Rakefile", "test/rails/app-2.1.2/app/controllers/application.rb", "test/rails/app-2.1.2/app/controllers/foo_controller.rb", "test/rails/app-2.1.2/app/helpers/application_helper.rb", "test/rails/app-2.1.2/config/boot.rb", "test/rails/app-2.1.2/config/database.yml", "test/rails/app-2.1.2/config/environment.rb", "test/rails/app-2.1.2/config/environments/development.rb", "test/rails/app-2.1.2/config/environments/production.rb", "test/rails/app-2.1.2/config/routes.rb", "test/rails/app-2.1.2/db/.gitignore", "test/rails/app-2.1.2/log/.gitignore", "test/rails/app-2.1.2/public/404.html", "test/rails/app-2.1.2/public/500.html", "test/rails/app-2.2.2/.gitignore", "test/rails/app-2.2.2/Rakefile", "test/rails/app-2.2.2/app/controllers/application.rb", "test/rails/app-2.2.2/app/controllers/foo_controller.rb", "test/rails/app-2.2.2/app/helpers/application_helper.rb", "test/rails/app-2.2.2/config/boot.rb", "test/rails/app-2.2.2/config/database.yml", "test/rails/app-2.2.2/config/environment.rb", "test/rails/app-2.2.2/config/environments/development.rb", "test/rails/app-2.2.2/config/environments/production.rb", "test/rails/app-2.2.2/config/routes.rb", "test/rails/app-2.2.2/db/.gitignore", "test/rails/app-2.2.2/log/.gitignore", "test/rails/app-2.2.2/public/404.html", "test/rails/app-2.2.2/public/500.html", "test/rails/app-2.3.2.1/.gitignore", "test/rails/app-2.3.2.1/Rakefile", "test/rails/app-2.3.2.1/app/controllers/application_controller.rb", "test/rails/app-2.3.2.1/app/controllers/foo_controller.rb", "test/rails/app-2.3.2.1/app/helpers/application_helper.rb", "test/rails/app-2.3.2.1/config/boot.rb", "test/rails/app-2.3.2.1/config/database.yml", "test/rails/app-2.3.2.1/config/environment.rb", "test/rails/app-2.3.2.1/config/environments/development.rb", "test/rails/app-2.3.2.1/config/environments/production.rb", "test/rails/app-2.3.2.1/config/routes.rb", "test/rails/app-2.3.2.1/db/.gitignore", "test/rails/app-2.3.2.1/log/.gitignore", "test/rails/app-2.3.2.1/public/404.html", "test/rails/app-2.3.2.1/public/500.html", "test/rails/test_rails.rb", "test/test_helper.rb", "test/tools/trickletest.rb", "test/unit/test_configurator.rb", "test/unit/test_http_parser.rb", "test/unit/test_request.rb", "test/unit/test_response.rb", "test/unit/test_server.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb", "test/unit/test_upload.rb", "unicorn.gemspec"]
|
15
|
+
s.files = [".document", ".gitignore", "CHANGELOG", "CONTRIBUTORS", "DESIGN", "GNUmakefile", "LICENSE", "Manifest", "PHILOSOPHY", "README", "Rakefile", "SIGNALS", "TODO", "TUNING", "bin/unicorn", "bin/unicorn_rails", "examples/init.sh", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb", "local.mk.sample", "setup.rb", "test/aggregate.rb", "test/benchmark/README", "test/benchmark/big_request.rb", "test/benchmark/dd.ru", "test/benchmark/request.rb", "test/benchmark/response.rb", "test/exec/README", "test/exec/test_exec.rb", "test/rails/app-1.2.3/.gitignore", "test/rails/app-1.2.3/Rakefile", "test/rails/app-1.2.3/app/controllers/application.rb", "test/rails/app-1.2.3/app/controllers/foo_controller.rb", "test/rails/app-1.2.3/app/helpers/application_helper.rb", "test/rails/app-1.2.3/config/boot.rb", "test/rails/app-1.2.3/config/database.yml", "test/rails/app-1.2.3/config/environment.rb", "test/rails/app-1.2.3/config/environments/development.rb", "test/rails/app-1.2.3/config/environments/production.rb", "test/rails/app-1.2.3/config/routes.rb", "test/rails/app-1.2.3/db/.gitignore", "test/rails/app-1.2.3/log/.gitignore", "test/rails/app-1.2.3/public/404.html", "test/rails/app-1.2.3/public/500.html", "test/rails/app-2.0.2/.gitignore", "test/rails/app-2.0.2/Rakefile", "test/rails/app-2.0.2/app/controllers/application.rb", "test/rails/app-2.0.2/app/controllers/foo_controller.rb", "test/rails/app-2.0.2/app/helpers/application_helper.rb", "test/rails/app-2.0.2/config/boot.rb", "test/rails/app-2.0.2/config/database.yml", "test/rails/app-2.0.2/config/environment.rb", "test/rails/app-2.0.2/config/environments/development.rb", "test/rails/app-2.0.2/config/environments/production.rb", "test/rails/app-2.0.2/config/routes.rb", "test/rails/app-2.0.2/db/.gitignore", "test/rails/app-2.0.2/log/.gitignore", "test/rails/app-2.0.2/public/404.html", "test/rails/app-2.0.2/public/500.html", "test/rails/app-2.1.2/.gitignore", "test/rails/app-2.1.2/Rakefile", "test/rails/app-2.1.2/app/controllers/application.rb", "test/rails/app-2.1.2/app/controllers/foo_controller.rb", "test/rails/app-2.1.2/app/helpers/application_helper.rb", "test/rails/app-2.1.2/config/boot.rb", "test/rails/app-2.1.2/config/database.yml", "test/rails/app-2.1.2/config/environment.rb", "test/rails/app-2.1.2/config/environments/development.rb", "test/rails/app-2.1.2/config/environments/production.rb", "test/rails/app-2.1.2/config/routes.rb", "test/rails/app-2.1.2/db/.gitignore", "test/rails/app-2.1.2/log/.gitignore", "test/rails/app-2.1.2/public/404.html", "test/rails/app-2.1.2/public/500.html", "test/rails/app-2.2.2/.gitignore", "test/rails/app-2.2.2/Rakefile", "test/rails/app-2.2.2/app/controllers/application.rb", "test/rails/app-2.2.2/app/controllers/foo_controller.rb", "test/rails/app-2.2.2/app/helpers/application_helper.rb", "test/rails/app-2.2.2/config/boot.rb", "test/rails/app-2.2.2/config/database.yml", "test/rails/app-2.2.2/config/environment.rb", "test/rails/app-2.2.2/config/environments/development.rb", "test/rails/app-2.2.2/config/environments/production.rb", "test/rails/app-2.2.2/config/routes.rb", "test/rails/app-2.2.2/db/.gitignore", "test/rails/app-2.2.2/log/.gitignore", "test/rails/app-2.2.2/public/404.html", "test/rails/app-2.2.2/public/500.html", "test/rails/app-2.3.2.1/.gitignore", "test/rails/app-2.3.2.1/Rakefile", "test/rails/app-2.3.2.1/app/controllers/application_controller.rb", "test/rails/app-2.3.2.1/app/controllers/foo_controller.rb", "test/rails/app-2.3.2.1/app/helpers/application_helper.rb", "test/rails/app-2.3.2.1/config/boot.rb", "test/rails/app-2.3.2.1/config/database.yml", "test/rails/app-2.3.2.1/config/environment.rb", "test/rails/app-2.3.2.1/config/environments/development.rb", "test/rails/app-2.3.2.1/config/environments/production.rb", "test/rails/app-2.3.2.1/config/routes.rb", "test/rails/app-2.3.2.1/db/.gitignore", "test/rails/app-2.3.2.1/log/.gitignore", "test/rails/app-2.3.2.1/public/404.html", "test/rails/app-2.3.2.1/public/500.html", "test/rails/test_rails.rb", "test/test_helper.rb", "test/tools/trickletest.rb", "test/unit/test_configurator.rb", "test/unit/test_http_parser.rb", "test/unit/test_request.rb", "test/unit/test_response.rb", "test/unit/test_server.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb", "test/unit/test_upload.rb", "test/unit/test_util.rb", "unicorn.gemspec"]
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.homepage = %q{http://unicorn.bogomips.org}
|
18
18
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Unicorn", "--main", "README"]
|
19
19
|
s.require_paths = ["lib", "ext"]
|
20
20
|
s.rubyforge_project = %q{unicorn}
|
21
|
-
s.rubygems_version = %q{1.3.
|
21
|
+
s.rubygems_version = %q{1.3.2}
|
22
22
|
s.summary = %q{A small fast HTTP library and server for Rack applications.}
|
23
|
-
s.test_files = ["test/unit/
|
23
|
+
s.test_files = ["test/unit/test_configurator.rb", "test/unit/test_response.rb", "test/unit/test_request.rb", "test/unit/test_signals.rb", "test/unit/test_upload.rb", "test/unit/test_http_parser.rb", "test/unit/test_socket_helper.rb", "test/unit/test_util.rb", "test/unit/test_server.rb"]
|
24
24
|
|
25
25
|
if s.respond_to? :specification_version then
|
26
26
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
|
-
s.specification_version =
|
27
|
+
s.specification_version = 3
|
28
28
|
|
29
29
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
30
30
|
else
|
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.7.
|
4
|
+
version: 0.7.1
|
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-
|
12
|
+
date: 2009-05-22 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -59,8 +59,10 @@ files:
|
|
59
59
|
- Rakefile
|
60
60
|
- SIGNALS
|
61
61
|
- TODO
|
62
|
+
- TUNING
|
62
63
|
- bin/unicorn
|
63
64
|
- bin/unicorn_rails
|
65
|
+
- examples/init.sh
|
64
66
|
- ext/unicorn/http11/ext_help.h
|
65
67
|
- ext/unicorn/http11/extconf.rb
|
66
68
|
- ext/unicorn/http11/http11.c
|
@@ -175,9 +177,12 @@ files:
|
|
175
177
|
- test/unit/test_signals.rb
|
176
178
|
- test/unit/test_socket_helper.rb
|
177
179
|
- test/unit/test_upload.rb
|
180
|
+
- test/unit/test_util.rb
|
178
181
|
- unicorn.gemspec
|
179
182
|
has_rdoc: true
|
180
183
|
homepage: http://unicorn.bogomips.org
|
184
|
+
licenses: []
|
185
|
+
|
181
186
|
post_install_message:
|
182
187
|
rdoc_options:
|
183
188
|
- --line-numbers
|
@@ -204,16 +209,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
209
|
requirements: []
|
205
210
|
|
206
211
|
rubyforge_project: unicorn
|
207
|
-
rubygems_version: 1.3.
|
212
|
+
rubygems_version: 1.3.2
|
208
213
|
signing_key:
|
209
|
-
specification_version:
|
214
|
+
specification_version: 3
|
210
215
|
summary: A small fast HTTP library and server for Rack applications.
|
211
216
|
test_files:
|
212
|
-
- test/unit/test_request.rb
|
213
|
-
- test/unit/test_http_parser.rb
|
214
|
-
- test/unit/test_server.rb
|
215
|
-
- test/unit/test_response.rb
|
216
217
|
- test/unit/test_configurator.rb
|
217
|
-
- test/unit/
|
218
|
+
- test/unit/test_response.rb
|
219
|
+
- test/unit/test_request.rb
|
218
220
|
- test/unit/test_signals.rb
|
221
|
+
- test/unit/test_upload.rb
|
222
|
+
- test/unit/test_http_parser.rb
|
219
223
|
- test/unit/test_socket_helper.rb
|
224
|
+
- test/unit/test_util.rb
|
225
|
+
- test/unit/test_server.rb
|