unicorn 0.97.1 → 0.98.0
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/.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
|