unicorn 0.96.1 → 0.97.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/.gitignore +1 -0
- data/Documentation/unicorn_rails.1.txt +6 -1
- data/FAQ +7 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -8
- data/KNOWN_ISSUES +8 -0
- data/Rakefile +1 -4
- data/TODO +1 -6
- data/bin/unicorn +4 -42
- data/bin/unicorn_rails +65 -68
- data/examples/init.sh +7 -2
- data/examples/logger_mp_safe.rb +25 -0
- data/ext/unicorn_http/CFLAGS +13 -0
- data/ext/unicorn_http/c_util.h +13 -0
- data/ext/unicorn_http/common_field_optimization.h +3 -3
- data/ext/unicorn_http/ext_help.h +2 -2
- data/ext/unicorn_http/global_variables.h +1 -3
- data/ext/unicorn_http/unicorn_http.rl +15 -13
- data/lib/unicorn.rb +64 -12
- data/lib/unicorn/configurator.rb +19 -1
- data/lib/unicorn/const.rb +4 -7
- data/lib/unicorn/http_request.rb +1 -1
- data/lib/unicorn/tee_input.rb +39 -39
- data/lib/unicorn/util.rb +1 -2
- data/t/.gitignore +2 -0
- data/t/GNUmakefile +67 -0
- data/t/README +42 -0
- data/t/bin/content-md5-put +36 -0
- data/t/bin/sha1sum.rb +23 -0
- data/t/bin/unused_listen +40 -0
- data/t/bin/utee +12 -0
- data/t/env.ru +3 -0
- data/t/my-tap-lib.sh +200 -0
- data/t/t0000-http-basic.sh +50 -0
- data/t/t0001-reload-bad-config.sh +52 -0
- data/t/t0002-config-conflict.sh +49 -0
- data/t/test-lib.sh +100 -0
- data/test/rails/test_rails.rb +3 -3
- data/test/test_helper.rb +5 -0
- data/test/unit/test_http_parser_ng.rb +0 -1
- data/test/unit/test_server.rb +1 -0
- data/test/unit/test_signals.rb +5 -1
- data/test/unit/test_tee_input.rb +15 -15
- data/test/unit/test_upload.rb +1 -0
- metadata +17 -2
data/.gitignore
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# NAME
|
6
6
|
|
7
|
-
unicorn_rails - a
|
7
|
+
unicorn_rails - a script/server-like command to launch the Unicorn HTTP server
|
8
8
|
|
9
9
|
# SYNOPSIS
|
10
10
|
|
@@ -16,6 +16,11 @@ A rackup(1)-like command to launch Rails applications using Unicorn. It
|
|
16
16
|
is expected to be started in your Rails application root (RAILS_ROOT),
|
17
17
|
but the "working_directory" directive may be used in the CONFIG_FILE.
|
18
18
|
|
19
|
+
It is designed to help Rails 1.x and 2.y users transition to Rack, but
|
20
|
+
it is NOT needed for Rails 3 applications. Rails 3 users are encouraged
|
21
|
+
to use unicorn(1) instead of unicorn_rails(1). Users of Rails 1.x/2.y
|
22
|
+
may also use unicorn(1) instead of unicorn_rails(1).
|
23
|
+
|
19
24
|
The outward interface resembles rackup(1), the internals and default
|
20
25
|
middleware loading is designed like the `script/server` command
|
21
26
|
distributed with Rails.
|
data/FAQ
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= Frequently Asked Questions about Unicorn
|
2
2
|
|
3
|
+
=== I've installed Rack 1.1.x, why can't Unicorn load Rails?
|
4
|
+
|
5
|
+
Rails 2.3.5 is not compatible with Rack 1.1.x. Unicorn is compatible
|
6
|
+
with both Rack 1.1.x and Rack 1.0.x, and RubyGems will load the latest
|
7
|
+
version of Rack installed on the system. Uninstalling the Rack 1.1.x
|
8
|
+
gem should solve gem loading issues with Rails 2.3.x.
|
9
|
+
|
3
10
|
=== Why are my redirects going to "http" URLs when my site uses https?
|
4
11
|
|
5
12
|
If your site is entirely behind https, then Rack applications that use
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,17 +1,13 @@
|
|
1
1
|
# use GNU Make to run tests in parallel, and without depending on RubyGems
|
2
2
|
all:: test
|
3
3
|
|
4
|
-
ruby = ruby
|
5
|
-
rake = rake
|
6
|
-
ragel = ragel
|
7
|
-
|
8
4
|
GIT_URL = git://git.bogomips.org/unicorn.git
|
9
5
|
RLFLAGS = -G2
|
10
6
|
|
11
7
|
# lower-case vars are deprecated
|
12
|
-
RUBY =
|
13
|
-
RAKE =
|
14
|
-
RAGEL =
|
8
|
+
RUBY = ruby
|
9
|
+
RAKE = rake
|
10
|
+
RAGEL = ragel
|
15
11
|
|
16
12
|
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
17
13
|
@./GIT-VERSION-GEN
|
@@ -62,6 +58,7 @@ lib/unicorn_http.$(DLEXT): $(ext)/unicorn_http.$(DLEXT)
|
|
62
58
|
install -m644 $< $@
|
63
59
|
http: lib/unicorn_http.$(DLEXT)
|
64
60
|
|
61
|
+
test-install: $(test_prefix)/.stamp
|
65
62
|
$(test_prefix)/.stamp: $(inst_deps)
|
66
63
|
mkdir -p $(test_prefix)/.ccache
|
67
64
|
tar cf - $(inst_deps) GIT-VERSION-GEN | \
|
@@ -163,7 +160,7 @@ NEWS: GIT-VERSION-FILE .manifest
|
|
163
160
|
$(RAKE) -s news_rdoc > $@+
|
164
161
|
mv $@+ $@
|
165
162
|
|
166
|
-
SINCE = 0.
|
163
|
+
SINCE = 0.96.0
|
167
164
|
ChangeLog: LOG_VERSION = \
|
168
165
|
$(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
|
169
166
|
echo $(GIT_VERSION) || git describe)
|
@@ -286,3 +283,4 @@ gem install-gem: GIT-VERSION-FILE
|
|
286
283
|
endif
|
287
284
|
|
288
285
|
.PHONY: .FORCE-GIT-VERSION-FILE doc $(T) $(slow_tests) manifest man
|
286
|
+
.PHONY: test-install
|
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
|
+
* When using "preload_app true", with apps using background threads
|
7
|
+
need to restart them in the after_fork hook because threads are never
|
8
|
+
shared with child processes. Additionally, any synchronization
|
9
|
+
primitives (Mutexes, Monitors, ConditionVariables) should be
|
10
|
+
reinitialized in case they are held during fork time to avoid
|
11
|
+
deadlocks. The core Ruby Logger class needlessly uses a MonitorMutex
|
12
|
+
which can be disabled with a {monkey patch}[link:examples/logger_mp_safe.rb]
|
13
|
+
|
6
14
|
* Rails 2.3.2 bundles its own version of Rack. This may cause subtle
|
7
15
|
bugs when simultaneously loaded with the system-wide Rack Rubygem
|
8
16
|
which Unicorn depends on. Upgrading to Rails 2.3.4 (or later) is
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
autoload :Gem, 'rubygems'
|
2
3
|
|
3
4
|
# most tasks are in the GNUmakefile which offers better parallelism
|
4
5
|
|
@@ -94,8 +95,6 @@ end
|
|
94
95
|
|
95
96
|
desc "print release notes for Rubyforge"
|
96
97
|
task :release_notes do
|
97
|
-
require 'rubygems'
|
98
|
-
|
99
98
|
spec = Gem::Specification.load('unicorn.gemspec')
|
100
99
|
puts spec.description.strip
|
101
100
|
puts ""
|
@@ -110,7 +109,6 @@ end
|
|
110
109
|
|
111
110
|
desc "post to RAA"
|
112
111
|
task :raa_update do
|
113
|
-
require 'rubygems'
|
114
112
|
require 'net/http'
|
115
113
|
require 'net/netrc'
|
116
114
|
rc = Net::Netrc.locate('unicorn-raa') or abort "~/.netrc not found"
|
@@ -177,7 +175,6 @@ end
|
|
177
175
|
|
178
176
|
# optional rake-compiler support in case somebody needs to cross compile
|
179
177
|
begin
|
180
|
-
require 'rubygems'
|
181
178
|
spec = Gem::Specification.load('unicorn.gemspec')
|
182
179
|
require 'rake/extensiontask'
|
183
180
|
unless test ?r, "ext/unicorn_http/unicorn_http.c"
|
data/TODO
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
* Documentation improvements
|
2
2
|
|
3
|
-
* ensure test suite passes on non-GNU/Linux systems
|
4
|
-
(likely that it already does)
|
5
|
-
|
6
|
-
* fix const-correctness in HTTP parser
|
7
|
-
|
8
3
|
* performance validation (esp. TeeInput)
|
9
4
|
|
10
|
-
* improve test suite
|
5
|
+
* improve test suite
|
data/bin/unicorn
CHANGED
@@ -108,52 +108,14 @@ opts = OptionParser.new("", 24, ' ') do |opts|
|
|
108
108
|
opts.parse! ARGV
|
109
109
|
end
|
110
110
|
|
111
|
-
|
112
|
-
abort "configuration file #{
|
113
|
-
|
114
|
-
if config =~ /\.ru$/
|
115
|
-
# parse embedded command-line options in config.ru comments
|
116
|
-
if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
|
117
|
-
opts.parse! $1.split(/\s+/)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
require 'pp' if $DEBUG
|
122
|
-
|
123
|
-
app = lambda do ||
|
124
|
-
# require Rack as late as possible in case $LOAD_PATH is modified
|
125
|
-
# in config.ru or command-line
|
126
|
-
inner_app = case config
|
127
|
-
when /\.ru$/
|
128
|
-
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
129
|
-
raw.sub!(/^__END__\n.*/, '')
|
130
|
-
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
131
|
-
else
|
132
|
-
require config
|
133
|
-
Object.const_get(File.basename(config, '.rb').capitalize)
|
134
|
-
end
|
135
|
-
pp({ :inner_app => inner_app }) if $DEBUG
|
136
|
-
case ENV["RACK_ENV"]
|
137
|
-
when "development"
|
138
|
-
Rack::Builder.new do
|
139
|
-
use Rack::CommonLogger, $stderr
|
140
|
-
use Rack::ShowExceptions
|
141
|
-
use Rack::Lint
|
142
|
-
run inner_app
|
143
|
-
end.to_app
|
144
|
-
when "deployment"
|
145
|
-
Rack::Builder.new do
|
146
|
-
use Rack::CommonLogger, $stderr
|
147
|
-
run inner_app
|
148
|
-
end.to_app
|
149
|
-
else
|
150
|
-
inner_app
|
151
|
-
end
|
152
|
-
end
|
111
|
+
ru = ARGV[0] || "config.ru"
|
112
|
+
abort "configuration file #{ru} not found" unless File.exist?(ru)
|
153
113
|
|
114
|
+
app = Unicorn.builder(ru, opts)
|
154
115
|
listeners << "#{host}:#{port}" if set_listener
|
155
116
|
|
156
117
|
if $DEBUG
|
118
|
+
require 'pp'
|
157
119
|
pp({
|
158
120
|
:unicorn_options => options,
|
159
121
|
:app => app,
|
data/bin/unicorn_rails
CHANGED
@@ -4,8 +4,6 @@ require 'unicorn/launcher'
|
|
4
4
|
require 'optparse'
|
5
5
|
require 'fileutils'
|
6
6
|
|
7
|
-
rails_pid = "#{Unicorn::HttpServer::START_CTX[:cwd]}/tmp/pids/unicorn.pid"
|
8
|
-
cmd = File.basename($0)
|
9
7
|
daemonize = false
|
10
8
|
listeners = []
|
11
9
|
options = { :listeners => listeners }
|
@@ -14,6 +12,7 @@ set_listener = false
|
|
14
12
|
ENV['RAILS_ENV'] ||= "development"
|
15
13
|
|
16
14
|
opts = OptionParser.new("", 24, ' ') do |opts|
|
15
|
+
cmd = File.basename($0)
|
17
16
|
opts.banner = "Usage: #{cmd} " \
|
18
17
|
"[ruby options] [#{cmd} options] [rackup config file]"
|
19
18
|
opts.separator "Ruby options:"
|
@@ -111,83 +110,81 @@ end
|
|
111
110
|
|
112
111
|
config = ARGV[0] || (File.exist?('config.ru') ? 'config.ru' : nil)
|
113
112
|
|
114
|
-
if config && config =~ /\.ru
|
113
|
+
if config && config =~ /\.ru\z/
|
115
114
|
# parse embedded command-line options in config.ru comments
|
116
|
-
|
117
|
-
opts.parse! $1.split(/\s+/)
|
118
|
-
end
|
115
|
+
/^#\\(.*)/ =~ File.read(config) and opts.parse!($1.split(/\s+/))
|
119
116
|
end
|
120
117
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
|
130
|
-
end
|
131
|
-
defined?(::RAILS_ROOT) or abort "RAILS_ROOT not defined by config/boot"
|
132
|
-
defined?(::RAILS_ENV) or abort "RAILS_ENV not defined by config/boot"
|
133
|
-
defined?(::Rails::VERSION::STRING) or
|
134
|
-
abort "Rails::VERSION::STRING not defined by config/boot"
|
135
|
-
|
136
|
-
inner_app = case config
|
137
|
-
when nil
|
138
|
-
require 'config/environment'
|
139
|
-
|
140
|
-
# it seems Rails >=2.2 support Rack, but only >=2.3 requires it
|
141
|
-
old_rails = case ::Rails::VERSION::MAJOR
|
142
|
-
when 0, 1 then true
|
143
|
-
when 2 then Rails::VERSION::MINOR < 3 ? true : false
|
144
|
-
else
|
145
|
-
false
|
118
|
+
def rails_builder(config, daemonize)
|
119
|
+
# this lambda won't run until after forking if preload_app is false
|
120
|
+
lambda do ||
|
121
|
+
# Load Rails and (possibly) the private version of Rack it bundles.
|
122
|
+
begin
|
123
|
+
require 'config/boot'
|
124
|
+
rescue LoadError => err
|
125
|
+
abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
|
146
126
|
end
|
147
127
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
Object.const_get(File.basename(config, '.rb').capitalize)
|
161
|
-
end
|
162
|
-
|
163
|
-
Rack::Builder.new do
|
164
|
-
map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
|
165
|
-
if inner_app.class.to_s == "Unicorn::App::OldRails"
|
166
|
-
if map_path != '/'
|
167
|
-
# patches + tests welcome, but I really cbf to deal with this
|
168
|
-
# since all apps I've ever dealt with just use "/" ...
|
169
|
-
$stderr.puts "relative URL roots may not work for older Rails"
|
128
|
+
inner_app = case config
|
129
|
+
when nil
|
130
|
+
require 'config/environment'
|
131
|
+
|
132
|
+
defined?(::Rails::VERSION::STRING) or
|
133
|
+
abort "Rails::VERSION::STRING not defined by config/{boot,environment}"
|
134
|
+
# it seems Rails >=2.2 support Rack, but only >=2.3 requires it
|
135
|
+
old_rails = case ::Rails::VERSION::MAJOR
|
136
|
+
when 0, 1 then true
|
137
|
+
when 2 then Rails::VERSION::MINOR < 3 ? true : false
|
138
|
+
else
|
139
|
+
false
|
170
140
|
end
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
141
|
+
|
142
|
+
if old_rails
|
143
|
+
require 'unicorn/app/old_rails'
|
144
|
+
Unicorn::App::OldRails.new
|
145
|
+
else
|
146
|
+
ActionController::Dispatcher.new
|
176
147
|
end
|
148
|
+
when /\.ru$/
|
149
|
+
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
150
|
+
raw.sub!(/^__END__\n.*/, '')
|
151
|
+
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
177
152
|
else
|
178
|
-
|
179
|
-
|
180
|
-
map(map_path) do
|
181
|
-
use Rails::Rack::Static
|
182
|
-
run inner_app
|
183
|
-
end
|
153
|
+
require config
|
154
|
+
Object.const_get(File.basename(config, '.rb').capitalize)
|
184
155
|
end
|
185
|
-
|
156
|
+
|
157
|
+
Rack::Builder.new do
|
158
|
+
map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
|
159
|
+
if inner_app.class.to_s == "Unicorn::App::OldRails"
|
160
|
+
if map_path != '/'
|
161
|
+
# patches + tests welcome, but I really cbf to deal with this
|
162
|
+
# since all apps I've ever dealt with just use "/" ...
|
163
|
+
$stderr.puts "relative URL roots may not work for older Rails"
|
164
|
+
end
|
165
|
+
$stderr.puts "LogTailer not available for Rails < 2.3" unless daemonize
|
166
|
+
$stderr.puts "Debugger not available" if $DEBUG
|
167
|
+
map(map_path) do
|
168
|
+
use Unicorn::App::OldRails::Static
|
169
|
+
run inner_app
|
170
|
+
end
|
171
|
+
else
|
172
|
+
use Rails::Rack::LogTailer unless daemonize
|
173
|
+
use Rails::Rack::Debugger if $DEBUG
|
174
|
+
map(map_path) do
|
175
|
+
use Rails::Rack::Static
|
176
|
+
run inner_app
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end.to_app
|
180
|
+
end
|
186
181
|
end
|
187
182
|
|
183
|
+
app = rails_builder(config, daemonize)
|
188
184
|
listeners << "#{host}:#{port}" if set_listener
|
189
185
|
|
190
186
|
if $DEBUG
|
187
|
+
require 'pp'
|
191
188
|
pp({
|
192
189
|
:unicorn_options => options,
|
193
190
|
:app => app,
|
@@ -196,12 +193,12 @@ if $DEBUG
|
|
196
193
|
end
|
197
194
|
|
198
195
|
# ensure Rails standard tmp paths exist
|
199
|
-
|
200
|
-
FileUtils.mkdir_p("tmp/#{
|
196
|
+
options[:after_reload] = lambda do
|
197
|
+
FileUtils.mkdir_p(%w(cache pids sessions sockets).map! { |d| "tmp/#{d}" })
|
201
198
|
end
|
202
199
|
|
203
200
|
if daemonize
|
204
|
-
options[:pid] =
|
201
|
+
options[:pid] = "tmp/pids/unicorn.pid"
|
205
202
|
Unicorn::Launcher.daemonize!(options)
|
206
203
|
end
|
207
204
|
Unicorn.run(app, options)
|
data/examples/init.sh
CHANGED
@@ -8,6 +8,8 @@ APP_ROOT=/home/x/my_app/current
|
|
8
8
|
PID=$APP_ROOT/tmp/pids/unicorn.pid
|
9
9
|
CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
|
10
10
|
INIT_CONF=$APP_ROOT/config/init.conf
|
11
|
+
action="$1"
|
12
|
+
set -u
|
11
13
|
|
12
14
|
test -f "$INIT_CONF" && . $INIT_CONF
|
13
15
|
|
@@ -23,7 +25,7 @@ oldsig () {
|
|
23
25
|
test -s $old_pid && kill -$1 `cat $old_pid`
|
24
26
|
}
|
25
27
|
|
26
|
-
case $
|
28
|
+
case $action in
|
27
29
|
start)
|
28
30
|
sig 0 && echo >&2 "Already running" && exit 0
|
29
31
|
$CMD
|
@@ -46,8 +48,11 @@ upgrade)
|
|
46
48
|
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
|
47
49
|
$CMD
|
48
50
|
;;
|
51
|
+
reopen-logs)
|
52
|
+
sig USR1
|
53
|
+
;;
|
49
54
|
*)
|
50
|
-
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop>"
|
55
|
+
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
|
51
56
|
exit 1
|
52
57
|
;;
|
53
58
|
esac
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Multi-Processing-safe monkey patch for Logger
|
2
|
+
#
|
3
|
+
# This monkey patch fixes the case where "preload_app true" is used and
|
4
|
+
# the application spawns a background thread upon being loaded.
|
5
|
+
#
|
6
|
+
# This removes all lock from the Logger code and solely relies on the
|
7
|
+
# underlying filesystem to handle write(2) system calls atomically when
|
8
|
+
# O_APPEND is used. This is safe in the presence of both multiple
|
9
|
+
# threads (native or green) and multiple processes when writing to
|
10
|
+
# a filesystem with POSIX O_APPEND semantics.
|
11
|
+
#
|
12
|
+
# It should be noted that the original locking on Logger could _never_ be
|
13
|
+
# considered reliable on non-POSIX filesystems with multiple processes,
|
14
|
+
# either, so nothing is lost in that case.
|
15
|
+
|
16
|
+
require 'logger'
|
17
|
+
class Logger::LogDevice
|
18
|
+
def write(message)
|
19
|
+
@dev.syswrite(message)
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
@dev.close
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# CFLAGS used for development (gcc-dependent)
|
2
|
+
# source this file if you want/need them
|
3
|
+
CFLAGS=
|
4
|
+
CFLAGS="$CFLAGS -Wall"
|
5
|
+
CFLAGS="$CFLAGS -Wwrite-strings"
|
6
|
+
CFLAGS="$CFLAGS -Wdeclaration-after-statement"
|
7
|
+
CFLAGS="$CFLAGS -Wcast-qual"
|
8
|
+
CFLAGS="$CFLAGS -Wstrict-prototypes"
|
9
|
+
CFLAGS="$CFLAGS -Wshadow"
|
10
|
+
CFLAGS="$CFLAGS -Wextra"
|
11
|
+
CFLAGS="$CFLAGS -Wno-deprecated-declarations"
|
12
|
+
CFLAGS="$CFLAGS -Waggregate-return"
|
13
|
+
CFLAGS="$CFLAGS -Wchar-subscripts"
|