unicorn 0.97.1 → 0.98.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +2 -2
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +10 -6
- data/KNOWN_ISSUES +20 -0
- data/README +13 -13
- data/Rakefile +9 -8
- data/bin/unicorn +3 -4
- data/bin/unicorn_rails +13 -14
- data/ext/unicorn_http/unicorn_http.rl +2 -6
- data/lib/unicorn.rb +30 -13
- data/lib/unicorn/const.rb +1 -1
- data/lib/unicorn/socket_helper.rb +2 -0
- data/test/rails/test_rails.rb +1 -1
- data/test/unit/test_http_parser_ng.rb +4 -0
- data/test/unit/test_server.rb +4 -0
- data/test/unit/test_tee_input.rb +30 -2
- data/test/unit/test_util.rb +5 -5
- metadata +3 -3
data/.document
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -41,6 +41,7 @@ c_files := $(ext)/unicorn_http.c $(wildcard $(ext)/*.h)
|
|
41
41
|
rl_files := $(wildcard $(ext)/*.rl)
|
42
42
|
base_bins := unicorn unicorn_rails
|
43
43
|
bins := $(addprefix bin/, $(base_bins))
|
44
|
+
man1_rdoc := $(addsuffix _1, $(base_bins))
|
44
45
|
man1_bins := $(addsuffix .1, $(base_bins))
|
45
46
|
man1_paths := $(addprefix man/man1/, $(man1_bins))
|
46
47
|
rb_files := $(bins) $(shell find lib ext -type f -name '*.rb')
|
@@ -160,7 +161,7 @@ NEWS: GIT-VERSION-FILE .manifest
|
|
160
161
|
$(RAKE) -s news_rdoc > $@+
|
161
162
|
mv $@+ $@
|
162
163
|
|
163
|
-
SINCE = 0.
|
164
|
+
SINCE = 0.97.1
|
164
165
|
ChangeLog: LOG_VERSION = \
|
165
166
|
$(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
|
166
167
|
echo $(GIT_VERSION) || git describe)
|
@@ -176,18 +177,21 @@ cgit_atom := http://git.bogomips.org/cgit/unicorn.git/atom/?h=master
|
|
176
177
|
atom = <link rel="alternate" title="Atom feed" href="$(1)" \
|
177
178
|
type="application/atom+xml"/>
|
178
179
|
|
179
|
-
# using rdoc 2.
|
180
|
+
# using rdoc 2.5.x+
|
180
181
|
doc: .document $(ext)/unicorn_http.c NEWS ChangeLog
|
181
|
-
for i in $(
|
182
|
+
for i in $(man1_rdoc); do echo > $$i; done
|
182
183
|
find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
183
|
-
rdoc -
|
184
|
+
rdoc -a -t "$(shell sed -ne '1s/^= //p' README)"
|
184
185
|
install -m644 COPYING doc/COPYING
|
185
186
|
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
186
187
|
$(MAKE) -C Documentation install-html install-man
|
187
188
|
install -m644 $(man1_paths) doc/
|
188
189
|
cd doc && for i in $(base_bins); do \
|
190
|
+
$(RM) 1.html $${i}.1.html; \
|
189
191
|
sed -e '/"documentation">/r man1/'$$i'.1.html' \
|
190
|
-
< $${i}_1.html > tmp && mv tmp $${i}_1.html;
|
192
|
+
< $${i}_1.html > tmp && mv tmp $${i}_1.html; \
|
193
|
+
ln $${i}_1.html $${i}.1.html; \
|
194
|
+
done
|
191
195
|
$(RUBY) -i -p -e \
|
192
196
|
'$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
|
193
197
|
doc/ChangeLog.html
|
@@ -196,7 +200,7 @@ doc: .document $(ext)/unicorn_http.c NEWS ChangeLog
|
|
196
200
|
doc/NEWS.html doc/README.html
|
197
201
|
$(RAKE) -s news_atom > doc/NEWS.atom.xml
|
198
202
|
cd doc && ln README.html tmp && mv tmp index.html
|
199
|
-
$(RM) $(
|
203
|
+
$(RM) $(man1_rdoc)
|
200
204
|
|
201
205
|
rails_git_url = git://github.com/rails/rails.git
|
202
206
|
rails_git := vendor/rails.git
|
data/KNOWN_ISSUES
CHANGED
@@ -3,6 +3,14 @@
|
|
3
3
|
Occasionally odd {issues}[link:ISSUES.html] arise without a transparent or
|
4
4
|
acceptable solution. Those issues are documented here.
|
5
5
|
|
6
|
+
* Under Ruby 1.9.1, methods like Array#shuffle and Array#sample will
|
7
|
+
segfault if called after forking. This is fixed in trunk (r26936) and
|
8
|
+
should be backported to the next 1.9.1 stable release (after p378).
|
9
|
+
Until then, it is advisable to call "Kernel.rand" in your after_fork
|
10
|
+
hook to reinitialize the random number generator.
|
11
|
+
|
12
|
+
See http://redmine.ruby-lang.org/issues/show/2962 for more details
|
13
|
+
|
6
14
|
* When using "preload_app true", with apps using background threads
|
7
15
|
need to restart them in the after_fork hook because threads are never
|
8
16
|
shared with child processes. Additionally, any synchronization
|
@@ -36,6 +44,18 @@ acceptable solution. Those issues are documented here.
|
|
36
44
|
where the unicorn gem is installed (e.g.
|
37
45
|
/usr/lib/ruby/gems/1.8/gems/unicorn-VERSION/lib)
|
38
46
|
|
47
|
+
With current versions of isolate, it is also recommended that you
|
48
|
+
disable it with the <tt>before_exec</tt> hook prevent the PATH and
|
49
|
+
RUBYOPT environment variable modifications from propagating between
|
50
|
+
upgrades in your Unicorn config file:
|
51
|
+
|
52
|
+
before_exec do |server|
|
53
|
+
Isolate.disable
|
54
|
+
end
|
55
|
+
|
56
|
+
Future versions (unreleased as of 2010.04.20) of isolate will not
|
57
|
+
require this as environment variable modifications will be idempotent.
|
58
|
+
|
39
59
|
* WONTFIX: code reloading and restarts with Sinatra 0.3.x (and likely older
|
40
60
|
versions) apps is broken. The workaround is to force production
|
41
61
|
mode to disable code reloading as well as disabling "run" in your
|
data/README
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Unicorn: Rack HTTP server for fast clients and Unix
|
2
2
|
|
3
|
-
Unicorn is an HTTP server for Rack applications designed to only serve
|
3
|
+
\Unicorn is an HTTP server for Rack applications designed to only serve
|
4
4
|
fast clients on low-latency, high-bandwidth connections and take
|
5
5
|
advantage of features in Unix/Unix-like kernels. Slow clients should
|
6
6
|
only be served by placing a reverse proxy capable of fully buffering
|
@@ -14,9 +14,9 @@ both the the request and response in between Unicorn and slow clients.
|
|
14
14
|
|
15
15
|
* Compatible with both Ruby 1.8 and 1.9. Rubinius support is in-progress.
|
16
16
|
|
17
|
-
* Process management: Unicorn will reap and restart workers that
|
17
|
+
* Process management: \Unicorn will reap and restart workers that
|
18
18
|
die from broken apps. There is no need to manage multiple processes
|
19
|
-
or ports yourself. Unicorn can spawn and manage any number of
|
19
|
+
or ports yourself. \Unicorn can spawn and manage any number of
|
20
20
|
worker processes you choose to scale to your backend.
|
21
21
|
|
22
22
|
* Load balancing is done entirely by the operating system kernel.
|
@@ -32,11 +32,11 @@ both the the request and response in between Unicorn and slow clients.
|
|
32
32
|
* Builtin reopening of all log files in your application via
|
33
33
|
USR1 signal. This allows logrotate to rotate files atomically and
|
34
34
|
quickly via rename instead of the racy and slow copytruncate method.
|
35
|
-
Unicorn also takes steps to ensure multi-line log entries from one
|
35
|
+
\Unicorn also takes steps to ensure multi-line log entries from one
|
36
36
|
request all stay within the same file.
|
37
37
|
|
38
38
|
* nginx-style binary upgrades without losing connections.
|
39
|
-
You can upgrade Unicorn, your entire application, libraries
|
39
|
+
You can upgrade \Unicorn, your entire application, libraries
|
40
40
|
and even your Ruby interpreter without dropping clients.
|
41
41
|
|
42
42
|
* before_fork and after_fork hooks in case your application
|
@@ -59,14 +59,14 @@ both the the request and response in between Unicorn and slow clients.
|
|
59
59
|
|
60
60
|
== License
|
61
61
|
|
62
|
-
Unicorn is copyright 2009 by all contributors (see logs in git).
|
62
|
+
\Unicorn is copyright 2009 by all contributors (see logs in git).
|
63
63
|
It is based on Mongrel and carries the same license.
|
64
64
|
|
65
65
|
Mongrel is copyright 2007 Zed A. Shaw and contributors. It is licensed
|
66
66
|
under the Ruby license and the GPL2. See the included LICENSE file for
|
67
67
|
details.
|
68
68
|
|
69
|
-
Unicorn is 100% Free Software.
|
69
|
+
\Unicorn is 100% Free Software.
|
70
70
|
|
71
71
|
== Install
|
72
72
|
|
@@ -111,17 +111,17 @@ In RAILS_ROOT, run:
|
|
111
111
|
|
112
112
|
unicorn_rails
|
113
113
|
|
114
|
-
Unicorn will bind to all interfaces on TCP port 8080 by default.
|
114
|
+
\Unicorn will bind to all interfaces on TCP port 8080 by default.
|
115
115
|
You may use the +--listen/-l+ switch to bind to a different
|
116
116
|
address:port or a UNIX socket.
|
117
117
|
|
118
118
|
=== Configuration File(s)
|
119
119
|
|
120
|
-
Unicorn will look for the config.ru file used by rackup in APP_ROOT.
|
120
|
+
\Unicorn will look for the config.ru file used by rackup in APP_ROOT.
|
121
121
|
|
122
|
-
For deployments, it can use a config file for Unicorn-specific options
|
122
|
+
For deployments, it can use a config file for \Unicorn-specific options
|
123
123
|
specified by the +--config-file/-c+ command-line switch. See
|
124
|
-
Unicorn::Configurator for the syntax of the Unicorn-specific options.
|
124
|
+
Unicorn::Configurator for the syntax of the \Unicorn-specific options.
|
125
125
|
The default settings are designed for maximum out-of-the-box
|
126
126
|
compatibility with existing applications.
|
127
127
|
|
@@ -134,7 +134,7 @@ options.
|
|
134
134
|
There is NO WARRANTY whatsoever if anything goes wrong, but
|
135
135
|
{let us know}[link:ISSUES.html] and we'll try our best to fix it.
|
136
136
|
|
137
|
-
Unicorn is designed to only serve fast clients either on the local host
|
137
|
+
\Unicorn is designed to only serve fast clients either on the local host
|
138
138
|
or a fast LAN. See the PHILOSOPHY and DESIGN documents for more details
|
139
139
|
regarding this.
|
140
140
|
|
@@ -144,6 +144,6 @@ All feedback (bug reports, user/development dicussion, patches, pull
|
|
144
144
|
requests) go to the mailing list/newsgroup. See the ISSUES document for
|
145
145
|
information on the {mailing list}[mailto:mongrel-unicorn@rubyforge.org].
|
146
146
|
|
147
|
-
For the latest on Unicorn releases, you may also finger us at
|
147
|
+
For the latest on \Unicorn releases, you may also finger us at
|
148
148
|
unicorn@bogomips.org or check our NEWS page (and subscribe to our Atom
|
149
149
|
feed).
|
data/Rakefile
CHANGED
@@ -175,16 +175,17 @@ end
|
|
175
175
|
|
176
176
|
# optional rake-compiler support in case somebody needs to cross compile
|
177
177
|
begin
|
178
|
-
spec = Gem::Specification.load('unicorn.gemspec')
|
179
|
-
require 'rake/extensiontask'
|
180
|
-
unless test ?r, "ext/unicorn_http/unicorn_http.c"
|
181
|
-
abort "run 'gmake ragel' or 'make ragel' to generate the Ragel source"
|
182
|
-
end
|
183
178
|
mk = "ext/unicorn_http/Makefile"
|
184
179
|
if test ?r, mk
|
185
|
-
|
186
|
-
|
180
|
+
warn "run 'gmake -C ext/unicorn_http clean' and\n" \
|
181
|
+
"remove #{mk} before using rake-compiler"
|
182
|
+
else
|
183
|
+
unless test ?r, "ext/unicorn_http/unicorn_http.c"
|
184
|
+
abort "run 'gmake ragel' or 'make ragel' to generate the Ragel source"
|
185
|
+
end
|
186
|
+
spec = Gem::Specification.load('unicorn.gemspec')
|
187
|
+
require 'rake/extensiontask'
|
188
|
+
Rake::ExtensionTask.new('unicorn_http', spec)
|
187
189
|
end
|
188
|
-
Rake::ExtensionTask.new('unicorn_http', spec)
|
189
190
|
rescue LoadError
|
190
191
|
end
|
data/bin/unicorn
CHANGED
@@ -5,8 +5,7 @@ require 'optparse'
|
|
5
5
|
|
6
6
|
ENV["RACK_ENV"] ||= "development"
|
7
7
|
daemonize = false
|
8
|
-
|
9
|
-
options = { :listeners => listeners }
|
8
|
+
options = { :listeners => [] }
|
10
9
|
host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
|
11
10
|
set_listener = false
|
12
11
|
|
@@ -81,7 +80,7 @@ opts = OptionParser.new("", 24, ' ') do |opts|
|
|
81
80
|
"listen on HOST:PORT or PATH",
|
82
81
|
"this may be specified multiple times",
|
83
82
|
"(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
|
84
|
-
listeners << address
|
83
|
+
options[:listeners] << address
|
85
84
|
end
|
86
85
|
|
87
86
|
opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
|
@@ -112,7 +111,7 @@ ru = ARGV[0] || "config.ru"
|
|
112
111
|
abort "configuration file #{ru} not found" unless File.exist?(ru)
|
113
112
|
|
114
113
|
app = Unicorn.builder(ru, opts)
|
115
|
-
listeners << "#{host}:#{port}" if set_listener
|
114
|
+
options[:listeners] << "#{host}:#{port}" if set_listener
|
116
115
|
|
117
116
|
if $DEBUG
|
118
117
|
require 'pp'
|
data/bin/unicorn_rails
CHANGED
@@ -5,8 +5,7 @@ require 'optparse'
|
|
5
5
|
require 'fileutils'
|
6
6
|
|
7
7
|
daemonize = false
|
8
|
-
|
9
|
-
options = { :listeners => listeners }
|
8
|
+
options = { :listeners => [] }
|
10
9
|
host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
|
11
10
|
set_listener = false
|
12
11
|
ENV['RAILS_ENV'] ||= "development"
|
@@ -70,7 +69,7 @@ opts = OptionParser.new("", 24, ' ') do |opts|
|
|
70
69
|
"listen on HOST:PORT or PATH",
|
71
70
|
"this may be specified multiple times",
|
72
71
|
"(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
|
73
|
-
listeners << address
|
72
|
+
options[:listeners] << address
|
74
73
|
end
|
75
74
|
|
76
75
|
opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
|
@@ -108,14 +107,14 @@ opts = OptionParser.new("", 24, ' ') do |opts|
|
|
108
107
|
opts.parse! ARGV
|
109
108
|
end
|
110
109
|
|
111
|
-
|
110
|
+
ru = ARGV[0] || (File.exist?('config.ru') ? 'config.ru' : nil)
|
112
111
|
|
113
|
-
if
|
112
|
+
if ru && ru =~ /\.ru\z/
|
114
113
|
# parse embedded command-line options in config.ru comments
|
115
|
-
/^#\\(.*)/ =~ File.read(
|
114
|
+
/^#\\(.*)/ =~ File.read(ru) and opts.parse!($1.split(/\s+/))
|
116
115
|
end
|
117
116
|
|
118
|
-
def rails_builder(
|
117
|
+
def rails_builder(ru, daemonize)
|
119
118
|
# this lambda won't run until after forking if preload_app is false
|
120
119
|
lambda do ||
|
121
120
|
# Load Rails and (possibly) the private version of Rack it bundles.
|
@@ -125,7 +124,7 @@ def rails_builder(config, daemonize)
|
|
125
124
|
abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
|
126
125
|
end
|
127
126
|
|
128
|
-
inner_app = case
|
127
|
+
inner_app = case ru
|
129
128
|
when nil
|
130
129
|
require 'config/environment'
|
131
130
|
|
@@ -146,12 +145,12 @@ def rails_builder(config, daemonize)
|
|
146
145
|
ActionController::Dispatcher.new
|
147
146
|
end
|
148
147
|
when /\.ru$/
|
149
|
-
raw = File.
|
148
|
+
raw = File.read(ru)
|
150
149
|
raw.sub!(/^__END__\n.*/, '')
|
151
|
-
eval("Rack::Builder.new {(#{raw}\n)}.to_app",
|
150
|
+
eval("Rack::Builder.new {(#{raw}\n)}.to_app", TOPLEVEL_BINDING, ru)
|
152
151
|
else
|
153
|
-
require
|
154
|
-
Object.const_get(File.basename(
|
152
|
+
require ru
|
153
|
+
Object.const_get(File.basename(ru, '.rb').capitalize)
|
155
154
|
end
|
156
155
|
|
157
156
|
Rack::Builder.new do
|
@@ -180,8 +179,8 @@ def rails_builder(config, daemonize)
|
|
180
179
|
end
|
181
180
|
end
|
182
181
|
|
183
|
-
app = rails_builder(
|
184
|
-
listeners << "#{host}:#{port}" if set_listener
|
182
|
+
app = rails_builder(ru, daemonize)
|
183
|
+
options[:listeners] << "#{host}:#{port}" if set_listener
|
185
184
|
|
186
185
|
if $DEBUG
|
187
186
|
require 'pp'
|
@@ -299,12 +299,8 @@ static void write_value(VALUE req, struct http_parser *hp,
|
|
299
299
|
}
|
300
300
|
|
301
301
|
action end_chunked_body {
|
302
|
-
|
303
|
-
|
304
|
-
cs = http_parser_en_Trailers;
|
305
|
-
} else {
|
306
|
-
cs = http_parser_first_final;
|
307
|
-
}
|
302
|
+
HP_FL_SET(hp, INTRAILER);
|
303
|
+
cs = http_parser_en_Trailers;
|
308
304
|
++p;
|
309
305
|
assert(p <= pe && "buffer overflow after chunked body");
|
310
306
|
goto post_exec;
|
data/lib/unicorn.rb
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
|
3
3
|
require 'fcntl'
|
4
|
-
require 'unicorn/socket_helper'
|
5
4
|
require 'etc'
|
5
|
+
require 'unicorn/socket_helper'
|
6
|
+
require 'unicorn/const'
|
7
|
+
require 'unicorn/http_request'
|
8
|
+
require 'unicorn/configurator'
|
9
|
+
require 'unicorn/util'
|
10
|
+
require 'unicorn/tee_input'
|
11
|
+
|
12
|
+
# autoload this so the app can prefer a different version, we
|
13
|
+
# don't rely on Rack itself for much and should be compatible for
|
14
|
+
# 1.0.x and 1.1.x+
|
6
15
|
autoload :Rack, 'rack'
|
7
16
|
|
8
17
|
# Unicorn module containing all of the classes (include C extensions) for running
|
@@ -17,12 +26,10 @@ module Unicorn
|
|
17
26
|
class ClientShutdown < EOFError
|
18
27
|
end
|
19
28
|
|
20
|
-
|
21
|
-
|
29
|
+
# we load HttpResponse last since it depends on Rack, and we
|
30
|
+
# want the application to be able to specify Rack (if they're
|
31
|
+
# *not* using config.ru)
|
22
32
|
autoload :HttpResponse, 'unicorn/http_response'
|
23
|
-
autoload :Configurator, 'unicorn/configurator'
|
24
|
-
autoload :TeeInput, 'unicorn/tee_input'
|
25
|
-
autoload :Util, 'unicorn/util'
|
26
33
|
|
27
34
|
class << self
|
28
35
|
def run(app, options = {})
|
@@ -71,6 +78,13 @@ module Unicorn
|
|
71
78
|
end
|
72
79
|
end
|
73
80
|
end
|
81
|
+
|
82
|
+
# returns an array of strings representing TCP listen socket addresses
|
83
|
+
# and Unix domain socket paths. This is useful for use with
|
84
|
+
# Raindrops::Middleware under Linux: http://raindrops.bogomips.org/
|
85
|
+
def listener_names
|
86
|
+
HttpServer::LISTENERS.map { |io| SocketHelper.sock_name(io) }
|
87
|
+
end
|
74
88
|
end
|
75
89
|
|
76
90
|
# This is the process manager of Unicorn. This manages worker
|
@@ -395,9 +409,12 @@ module Unicorn
|
|
395
409
|
# machine) comes out of suspend/hibernation
|
396
410
|
if (last_check + timeout) >= (last_check = Time.now)
|
397
411
|
murder_lazy_workers
|
412
|
+
else
|
413
|
+
# wait for workers to wakeup on suspend
|
414
|
+
master_sleep(timeout/2.0 + 1)
|
398
415
|
end
|
399
416
|
maintain_worker_count if respawn
|
400
|
-
master_sleep
|
417
|
+
master_sleep(1)
|
401
418
|
when :QUIT # graceful shutdown
|
402
419
|
break
|
403
420
|
when :TERM, :INT # immediate shutdown
|
@@ -478,9 +495,9 @@ module Unicorn
|
|
478
495
|
|
479
496
|
# wait for a signal hander to wake us up and then consume the pipe
|
480
497
|
# Wake up every second anyways to run murder_lazy_workers
|
481
|
-
def master_sleep
|
498
|
+
def master_sleep(sec)
|
482
499
|
begin
|
483
|
-
ready = IO.select([SELF_PIPE.first], nil, nil,
|
500
|
+
ready = IO.select([SELF_PIPE.first], nil, nil, sec) or return
|
484
501
|
ready.first && ready.first.first or return
|
485
502
|
loop { SELF_PIPE.first.read_nonblock(Const::CHUNK_SIZE) }
|
486
503
|
rescue Errno::EAGAIN, Errno::EINTR
|
@@ -800,15 +817,15 @@ module Unicorn
|
|
800
817
|
|
801
818
|
def build_app!
|
802
819
|
if app.respond_to?(:arity) && app.arity == 0
|
803
|
-
# exploit COW in case of preload_app. Also avoids race
|
804
|
-
# conditions in Rainbows! since load/require are not thread-safe
|
805
|
-
Unicorn.constants.each { |x| Unicorn.const_get(x) }
|
806
|
-
|
807
820
|
if defined?(Gem) && Gem.respond_to?(:refresh)
|
808
821
|
logger.info "Refreshing Gem list"
|
809
822
|
Gem.refresh
|
810
823
|
end
|
811
824
|
self.app = app.call
|
825
|
+
|
826
|
+
# exploit COW in case of preload_app. Also avoids race
|
827
|
+
# conditions in Rainbows! since load/require are not thread-safe
|
828
|
+
Unicorn.const_get :HttpResponse
|
812
829
|
end
|
813
830
|
end
|
814
831
|
|
data/lib/unicorn/const.rb
CHANGED
@@ -7,7 +7,7 @@ module Unicorn
|
|
7
7
|
# gave about a 3% to 10% performance improvement over using the strings directly.
|
8
8
|
# Symbols did not really improve things much compared to constants.
|
9
9
|
module Const
|
10
|
-
UNICORN_VERSION="0.
|
10
|
+
UNICORN_VERSION="0.98.0"
|
11
11
|
|
12
12
|
DEFAULT_HOST = "0.0.0.0" # default TCP listen host address
|
13
13
|
DEFAULT_PORT = 8080 # default TCP listen port
|
data/test/rails/test_rails.rb
CHANGED
@@ -234,7 +234,7 @@ logger Logger.new('#{COMMON_TMP.path}')
|
|
234
234
|
def test_alt_url_root_config_env
|
235
235
|
# cbf to actually work on this since I never use this feature (ewong)
|
236
236
|
return unless ROR_V[0] >= 2 && ROR_V[1] >= 3
|
237
|
-
tmp = Tempfile.new(
|
237
|
+
tmp = Tempfile.new('')
|
238
238
|
tmp.syswrite("ENV['RAILS_RELATIVE_URL_ROOT'] = '/poo'\n")
|
239
239
|
redirect_test_io do
|
240
240
|
@pid = fork { exec 'unicorn_rails', "-l#@addr:#@port", "-c", tmp.path }
|
@@ -172,6 +172,10 @@ class HttpParserNgTest < Test::Unit::TestCase
|
|
172
172
|
assert_equal '', str
|
173
173
|
assert ! @parser.body_eof?
|
174
174
|
assert_equal "", @parser.filter_body(tmp, "\r\n0\r\n")
|
175
|
+
assert_equal "", tmp
|
176
|
+
assert @parser.body_eof?
|
177
|
+
assert_equal req, @parser.trailers(req, moo = "\r\n")
|
178
|
+
assert_equal "", moo
|
175
179
|
assert @parser.body_eof?
|
176
180
|
assert ! @parser.keepalive?
|
177
181
|
end
|
data/test/unit/test_server.rb
CHANGED
data/test/unit/test_tee_input.rb
CHANGED
@@ -160,7 +160,7 @@ class TestTeeInput < Test::Unit::TestCase
|
|
160
160
|
pid = fork {
|
161
161
|
@rd.close
|
162
162
|
5.times { @wr.write("5\r\nabcde\r\n") }
|
163
|
-
@wr.write("0\r\n")
|
163
|
+
@wr.write("0\r\n\r\n")
|
164
164
|
}
|
165
165
|
@wr.close
|
166
166
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
@@ -199,7 +199,7 @@ class TestTeeInput < Test::Unit::TestCase
|
|
199
199
|
rd.read(1) == "." and
|
200
200
|
@wr.write("#{'%x' % [ chunk.size]}\r\n#{chunk}\r\n")
|
201
201
|
end
|
202
|
-
@wr.write("0\r\n")
|
202
|
+
@wr.write("0\r\n\r\n")
|
203
203
|
}
|
204
204
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
205
205
|
assert_nil @parser.content_length
|
@@ -213,6 +213,34 @@ class TestTeeInput < Test::Unit::TestCase
|
|
213
213
|
assert status.success?
|
214
214
|
end
|
215
215
|
|
216
|
+
def test_chunked_with_trailer
|
217
|
+
@parser = Unicorn::HttpParser.new
|
218
|
+
@buf = "POST / HTTP/1.1\r\n" \
|
219
|
+
"Host: localhost\r\n" \
|
220
|
+
"Trailer: Hello\r\n" \
|
221
|
+
"Transfer-Encoding: chunked\r\n" \
|
222
|
+
"\r\n"
|
223
|
+
assert_equal @env, @parser.headers(@env, @buf)
|
224
|
+
assert_equal "", @buf
|
225
|
+
|
226
|
+
pid = fork {
|
227
|
+
@rd.close
|
228
|
+
5.times { @wr.write("5\r\nabcde\r\n") }
|
229
|
+
@wr.write("0\r\n")
|
230
|
+
@wr.write("Hello: World\r\n\r\n")
|
231
|
+
}
|
232
|
+
@wr.close
|
233
|
+
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
234
|
+
assert_nil @parser.content_length
|
235
|
+
assert_nil ti.len
|
236
|
+
assert ! @parser.body_eof?
|
237
|
+
assert_equal 25, ti.size
|
238
|
+
assert_equal "World", @env['HTTP_HELLO']
|
239
|
+
status = nil
|
240
|
+
assert_nothing_raised { pid, status = Process.waitpid2(pid) }
|
241
|
+
assert status.success?
|
242
|
+
end
|
243
|
+
|
216
244
|
private
|
217
245
|
|
218
246
|
def init_parser(body, size = nil)
|
data/test/unit/test_util.rb
CHANGED
@@ -7,7 +7,7 @@ class TestUtil < Test::Unit::TestCase
|
|
7
7
|
|
8
8
|
EXPECT_FLAGS = File::WRONLY | File::APPEND
|
9
9
|
def test_reopen_logs_noop
|
10
|
-
tmp = Tempfile.new(
|
10
|
+
tmp = Tempfile.new('')
|
11
11
|
tmp.reopen(tmp.path, 'a')
|
12
12
|
tmp.sync = true
|
13
13
|
ext = tmp.external_encoding rescue nil
|
@@ -21,14 +21,14 @@ class TestUtil < Test::Unit::TestCase
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def test_reopen_logs_renamed
|
24
|
-
tmp = Tempfile.new(
|
24
|
+
tmp = Tempfile.new('')
|
25
25
|
tmp_path = tmp.path.freeze
|
26
26
|
tmp.reopen(tmp_path, 'a')
|
27
27
|
tmp.sync = true
|
28
28
|
ext = tmp.external_encoding rescue nil
|
29
29
|
int = tmp.internal_encoding rescue nil
|
30
30
|
before = tmp.stat.inspect
|
31
|
-
to = Tempfile.new(
|
31
|
+
to = Tempfile.new('')
|
32
32
|
File.rename(tmp_path, to.path)
|
33
33
|
assert ! File.exist?(tmp_path)
|
34
34
|
Unicorn::Util.reopen_logs
|
@@ -45,7 +45,7 @@ class TestUtil < Test::Unit::TestCase
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_reopen_logs_renamed_with_encoding
|
48
|
-
tmp = Tempfile.new(
|
48
|
+
tmp = Tempfile.new('')
|
49
49
|
tmp_path = tmp.path.dup.freeze
|
50
50
|
Encoding.list.each { |encoding|
|
51
51
|
File.open(tmp_path, "a:#{encoding.to_s}") { |fp|
|
@@ -68,7 +68,7 @@ class TestUtil < Test::Unit::TestCase
|
|
68
68
|
end if STDIN.respond_to?(:external_encoding)
|
69
69
|
|
70
70
|
def test_reopen_logs_renamed_with_internal_encoding
|
71
|
-
tmp = Tempfile.new(
|
71
|
+
tmp = Tempfile.new('')
|
72
72
|
tmp_path = tmp.path.dup.freeze
|
73
73
|
Encoding.list.each { |ext|
|
74
74
|
Encoding.list.each { |int|
|
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.
|
4
|
+
version: 0.98.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Unicorn hackers
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-05-05 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
25
|
description: |-
|
26
|
-
Unicorn is an HTTP server for Rack applications designed to only serve
|
26
|
+
\Unicorn is an HTTP server for Rack applications designed to only serve
|
27
27
|
fast clients on low-latency, high-bandwidth connections and take
|
28
28
|
advantage of features in Unix/Unix-like kernels. Slow clients should
|
29
29
|
only be served by placing a reverse proxy capable of fully buffering
|