unicorn 0.990.0.5.gbfb1 → 0.991.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +1 -1
- data/README +2 -2
- data/Rakefile +13 -8
- data/SIGNALS +6 -1
- data/bin/unicorn +1 -4
- data/bin/unicorn_rails +17 -10
- data/examples/init.sh +17 -1
- data/ext/unicorn_http/ext_help.h +2 -6
- data/ext/unicorn_http/extconf.rb +1 -5
- data/lib/unicorn.rb +3 -4
- data/lib/unicorn/configurator.rb +74 -6
- data/lib/unicorn/const.rb +2 -2
- data/lib/unicorn/launcher.rb +31 -32
- data/t/my-tap-lib.sh +3 -2
- data/t/t0003-working_directory.sh +56 -0
- data/t/t0004-working_directory_broken.sh +24 -0
- data/t/t0005-working_directory_app.rb.sh +37 -0
- data/t/t0300-rails3-basic.sh +1 -1
- data/t/t0302-rails3-alt-working_directory.sh +32 -0
- data/t/t0303-rails3-alt-working_directory_config.ru.sh +58 -0
- data/t/test-lib.sh +10 -1
- data/t/test-rails3.sh +1 -1
- data/test/test_helper.rb +3 -0
- data/unicorn.gemspec +1 -1
- metadata +44 -17
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -168,7 +168,7 @@ NEWS: GIT-VERSION-FILE .manifest
|
|
168
168
|
$(RAKE) -s news_rdoc > $@+
|
169
169
|
mv $@+ $@
|
170
170
|
|
171
|
-
SINCE = 0.
|
171
|
+
SINCE = 0.990.0
|
172
172
|
ChangeLog: LOG_VERSION = \
|
173
173
|
$(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
|
174
174
|
echo $(GIT_VERSION) || git describe)
|
data/README
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
= Unicorn: Rack HTTP server for fast clients and Unix
|
1
|
+
= \Unicorn: Rack HTTP server for fast clients and Unix
|
2
2
|
|
3
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
|
7
|
-
both the the request and response in between Unicorn and slow clients.
|
7
|
+
both the the request and response in between \Unicorn and slow clients.
|
8
8
|
|
9
9
|
== Features
|
10
10
|
|
data/Rakefile
CHANGED
@@ -179,7 +179,7 @@ begin
|
|
179
179
|
if File.readable?(mk)
|
180
180
|
warn "run 'gmake -C ext/unicorn_http clean' and\n" \
|
181
181
|
"remove #{mk} before using rake-compiler"
|
182
|
-
|
182
|
+
elsif ENV['VERSION']
|
183
183
|
unless File.readable?("ext/unicorn_http/unicorn_http.c")
|
184
184
|
abort "run 'gmake ragel' or 'make ragel' to generate the Ragel source"
|
185
185
|
end
|
@@ -192,21 +192,26 @@ end
|
|
192
192
|
|
193
193
|
task :isolate do
|
194
194
|
require 'isolate'
|
195
|
+
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
195
196
|
opts = {
|
196
197
|
:system => false,
|
197
|
-
:path => "tmp/isolate
|
198
|
+
:path => "tmp/isolate/#{ruby_engine}-#{RUBY_VERSION}",
|
198
199
|
:multiruby => false, # we want "1.8.7" instead of "1.8"
|
199
200
|
}
|
201
|
+
fp = File.open(__FILE__, "rb")
|
202
|
+
fp.flock(File::LOCK_EX)
|
200
203
|
|
201
204
|
# C extensions aren't binary-compatible across Ruby versions
|
202
|
-
fork { Isolate.now!(opts) { gem 'sqlite3-ruby', '1.2.5' } }
|
205
|
+
pid = fork { Isolate.now!(opts) { gem 'sqlite3-ruby', '1.2.5' } }
|
206
|
+
_, status = Process.waitpid2(pid)
|
207
|
+
status.success? or abort status.inspect
|
203
208
|
|
204
209
|
# pure Ruby gems can be shared across all Rubies
|
205
|
-
%w(3.0.0.
|
210
|
+
%w(3.0.0.beta4).each do |rails_ver|
|
206
211
|
opts[:path] = "tmp/isolate/rails-#{rails_ver}"
|
207
|
-
fork { Isolate.now!(opts) { gem 'rails', rails_ver } }
|
212
|
+
pid = fork { Isolate.now!(opts) { gem 'rails', rails_ver } }
|
213
|
+
_, status = Process.waitpid2(pid)
|
214
|
+
status.success? or abort status.inspect
|
208
215
|
end
|
209
|
-
|
210
|
-
failed = Process.waitall.delete_if { |(_,status)| status.success? }
|
211
|
-
abort failed.inspect unless failed.empty?
|
216
|
+
fp.flock(File::LOCK_UN)
|
212
217
|
end
|
data/SIGNALS
CHANGED
@@ -14,7 +14,12 @@ Unicorn and nginx.
|
|
14
14
|
will also pick up any application code changes when restarted. If
|
15
15
|
"preload_app" is true, then application code changes will have no
|
16
16
|
effect; USR2 + QUIT (see below) must be used to load newer code in
|
17
|
-
this case.
|
17
|
+
this case. When reloading the application, +Gem.refresh+ will
|
18
|
+
be called so updated code for your application can pick up newly
|
19
|
+
installed RubyGems. It is not recommended that you uninstall
|
20
|
+
libraries your application depends on while Unicorn is running,
|
21
|
+
as respawned workers may enter a spawn loop when they fail to
|
22
|
+
load an uninstalled dependency.
|
18
23
|
|
19
24
|
* INT/TERM - quick shutdown, kills all workers immediately
|
20
25
|
|
data/bin/unicorn
CHANGED
@@ -107,10 +107,7 @@ opts = OptionParser.new("", 24, ' ') do |opts|
|
|
107
107
|
opts.parse! ARGV
|
108
108
|
end
|
109
109
|
|
110
|
-
|
111
|
-
abort "configuration file #{ru} not found" unless File.exist?(ru)
|
112
|
-
|
113
|
-
app = Unicorn.builder(ru, opts)
|
110
|
+
app = Unicorn.builder(ARGV[0] || 'config.ru', opts)
|
114
111
|
options[:listeners] << "#{host}:#{port}" if set_listener
|
115
112
|
|
116
113
|
if $DEBUG
|
data/bin/unicorn_rails
CHANGED
@@ -107,8 +107,6 @@ opts = OptionParser.new("", 24, ' ') do |opts|
|
|
107
107
|
opts.parse! ARGV
|
108
108
|
end
|
109
109
|
|
110
|
-
ru = ARGV[0] || (File.exist?('config.ru') ? 'config.ru' : nil)
|
111
|
-
|
112
110
|
def rails_dispatcher
|
113
111
|
if ::Rails::VERSION::MAJOR >= 3 && ::File.exist?('config/application.rb')
|
114
112
|
if ::File.read('config/application.rb') =~ /^module\s+([\w:]+)\s*$/
|
@@ -127,9 +125,20 @@ def rails_dispatcher
|
|
127
125
|
result || abort("Unable to locate the application dispatcher class")
|
128
126
|
end
|
129
127
|
|
130
|
-
def rails_builder(daemonize)
|
128
|
+
def rails_builder(ru, opts, daemonize)
|
129
|
+
return Unicorn.builder(ru, opts) if ru
|
130
|
+
|
131
|
+
# allow Configurator to parse cli switches embedded in the ru file
|
132
|
+
Unicorn::Configurator::RACKUP.update(:file => :rails, :optparse => opts)
|
133
|
+
|
131
134
|
# this lambda won't run until after forking if preload_app is false
|
135
|
+
# this runs after config file reloading
|
132
136
|
lambda do ||
|
137
|
+
# Rails 3 includes a config.ru, use it if we find it after
|
138
|
+
# working_directory is bound.
|
139
|
+
::File.exist?('config.ru') and
|
140
|
+
return Unicorn.builder('config.ru', opts).call
|
141
|
+
|
133
142
|
# Load Rails and (possibly) the private version of Rack it bundles.
|
134
143
|
begin
|
135
144
|
require ::File.expand_path('config/boot')
|
@@ -154,10 +163,10 @@ def rails_builder(daemonize)
|
|
154
163
|
if map_path != '/'
|
155
164
|
# patches + tests welcome, but I really cbf to deal with this
|
156
165
|
# since all apps I've ever dealt with just use "/" ...
|
157
|
-
|
166
|
+
warn "relative URL roots may not work for older Rails"
|
158
167
|
end
|
159
|
-
|
160
|
-
|
168
|
+
warn "LogTailer not available for Rails < 2.3" unless daemonize
|
169
|
+
warn "Debugger not available" if $DEBUG
|
161
170
|
require 'unicorn/app/old_rails'
|
162
171
|
map(map_path) do
|
163
172
|
use Unicorn::App::OldRails::Static
|
@@ -167,9 +176,7 @@ def rails_builder(daemonize)
|
|
167
176
|
use Rails::Rack::LogTailer unless daemonize
|
168
177
|
use Rails::Rack::Debugger if $DEBUG
|
169
178
|
map(map_path) do
|
170
|
-
|
171
|
-
use ActionDispatch::Static, "#{Rails.root}/public"
|
172
|
-
else
|
179
|
+
unless defined?(ActionDispatch::Static)
|
173
180
|
use Rails::Rack::Static
|
174
181
|
end
|
175
182
|
run rails_dispatcher
|
@@ -179,7 +186,7 @@ def rails_builder(daemonize)
|
|
179
186
|
end
|
180
187
|
end
|
181
188
|
|
182
|
-
app =
|
189
|
+
app = rails_builder(ARGV[0], opts, daemonize)
|
183
190
|
options[:listeners] << "#{host}:#{port}" if set_listener
|
184
191
|
|
185
192
|
if $DEBUG
|
data/examples/init.sh
CHANGED
@@ -4,6 +4,7 @@ set -e
|
|
4
4
|
# since nginx and unicorn accept the same signals
|
5
5
|
|
6
6
|
# Feel free to change any of the following variables for your app:
|
7
|
+
TIMEOUT=${TIMEOUT-60}
|
7
8
|
APP_ROOT=/home/x/my_app/current
|
8
9
|
PID=$APP_ROOT/tmp/pids/unicorn.pid
|
9
10
|
CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
|
@@ -44,7 +45,22 @@ restart|reload)
|
|
44
45
|
$CMD
|
45
46
|
;;
|
46
47
|
upgrade)
|
47
|
-
sig USR2 && sleep 2 && sig 0 && oldsig QUIT
|
48
|
+
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
|
49
|
+
then
|
50
|
+
n=$TIMEOUT
|
51
|
+
while test -s $old_pid && test $n -ge 0
|
52
|
+
do
|
53
|
+
printf '.' && sleep 1 && n=$(( $n - 1 ))
|
54
|
+
done
|
55
|
+
echo
|
56
|
+
|
57
|
+
if test $n -lt 0 && test -s $old_pid
|
58
|
+
then
|
59
|
+
echo >&2 "$old_pid still exists after $TIMEOUT seconds"
|
60
|
+
exit 1
|
61
|
+
fi
|
62
|
+
exit 0
|
63
|
+
fi
|
48
64
|
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
|
49
65
|
$CMD
|
50
66
|
;;
|
data/ext/unicorn_http/ext_help.h
CHANGED
@@ -10,22 +10,18 @@
|
|
10
10
|
|
11
11
|
#ifndef RUBINIUS
|
12
12
|
# define rb_str_update(x) do {} while (0)
|
13
|
-
# define rb_str_flush(x) do {} while (0)
|
14
13
|
#endif /* !RUBINIUS */
|
15
14
|
|
16
15
|
#ifndef HAVE_RB_STR_SET_LEN
|
17
16
|
# ifdef RUBINIUS
|
18
|
-
#
|
19
|
-
#
|
17
|
+
# error we should never get here with current Rubinius (1.x)
|
18
|
+
# endif
|
20
19
|
/* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
|
21
20
|
static void rb_18_str_set_len(VALUE str, long len)
|
22
21
|
{
|
23
22
|
RSTRING(str)->len = len;
|
24
23
|
RSTRING(str)->ptr[len] = '\0';
|
25
|
-
rb_str_flush(str);
|
26
24
|
}
|
27
|
-
# define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
|
28
|
-
# endif /* ! RUBINIUS */
|
29
25
|
#endif /* !defined(HAVE_RB_STR_SET_LEN) */
|
30
26
|
|
31
27
|
/* not all Ruby implementations support frozen objects (Rubinius does not) */
|
data/ext/unicorn_http/extconf.rb
CHANGED
@@ -6,9 +6,5 @@ dir_config("unicorn_http")
|
|
6
6
|
have_macro("SIZEOF_OFF_T", "ruby.h") or check_sizeof("off_t", "sys/types.h")
|
7
7
|
have_macro("SIZEOF_LONG", "ruby.h") or check_sizeof("long", "sys/types.h")
|
8
8
|
have_func("rb_str_set_len", "ruby.h")
|
9
|
-
have_func("rb_str_modify", "ruby.h")
|
10
9
|
|
11
|
-
|
12
|
-
with_cflags($CFLAGS + " -fPIC ") do
|
13
|
-
create_makefile("unicorn_http")
|
14
|
-
end
|
10
|
+
create_makefile("unicorn_http")
|
data/lib/unicorn.rb
CHANGED
@@ -33,11 +33,10 @@ module Unicorn
|
|
33
33
|
# Unicorn config). The returned lambda will be called when it is
|
34
34
|
# time to build the app.
|
35
35
|
def builder(ru, opts)
|
36
|
-
|
37
|
-
|
38
|
-
/^#\\(.*)/ =~ File.read(ru) and opts.parse!($1.split(/\s+/))
|
39
|
-
end
|
36
|
+
# allow Configurator to parse cli switches embedded in the ru file
|
37
|
+
Unicorn::Configurator::RACKUP.update(:file => ru, :optparse => opts)
|
40
38
|
|
39
|
+
# always called after config file parsing, may be called after forking
|
41
40
|
lambda do ||
|
42
41
|
inner_app = case ru
|
43
42
|
when /\.ru$/
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -13,6 +13,12 @@ module Unicorn
|
|
13
13
|
# nginx is also available at
|
14
14
|
# http://unicorn.bogomips.org/examples/nginx.conf
|
15
15
|
class Configurator < Struct.new(:set, :config_file, :after_reload)
|
16
|
+
# :stopdoc:
|
17
|
+
# used to stash stuff for deferred processing of cli options in
|
18
|
+
# config.ru after "working_directory" is bound. Do not rely on
|
19
|
+
# this being around later on...
|
20
|
+
RACKUP = {}
|
21
|
+
# :startdoc:
|
16
22
|
|
17
23
|
# Default settings for Unicorn
|
18
24
|
DEFAULTS = {
|
@@ -51,6 +57,11 @@ module Unicorn
|
|
51
57
|
def reload #:nodoc:
|
52
58
|
instance_eval(File.read(config_file), config_file) if config_file
|
53
59
|
|
60
|
+
parse_rackup_file
|
61
|
+
|
62
|
+
# unicorn_rails creates dirs here after working_directory is bound
|
63
|
+
after_reload.call if after_reload
|
64
|
+
|
54
65
|
# working_directory binds immediately (easier error checking that way),
|
55
66
|
# now ensure any paths we changed are correctly set.
|
56
67
|
[ :pid, :stderr_path, :stdout_path ].each do |var|
|
@@ -59,13 +70,13 @@ module Unicorn
|
|
59
70
|
File.writable?(path) || File.writable?(File.dirname(path)) or \
|
60
71
|
raise ArgumentError, "directory for #{var}=#{path} not writable"
|
61
72
|
end
|
62
|
-
|
63
|
-
# unicorn_rails creates dirs here after working_directory is bound
|
64
|
-
after_reload.call if after_reload
|
65
73
|
end
|
66
74
|
|
67
75
|
def commit!(server, options = {}) #:nodoc:
|
68
76
|
skip = options[:skip] || []
|
77
|
+
if ready_pipe = RACKUP.delete(:ready_pipe)
|
78
|
+
server.ready_pipe = ready_pipe
|
79
|
+
end
|
69
80
|
set.each do |key, value|
|
70
81
|
value == :unset and next
|
71
82
|
skip.include?(key) and next
|
@@ -300,7 +311,22 @@ module Unicorn
|
|
300
311
|
#
|
301
312
|
# In addition to reloading the unicorn-specific config settings,
|
302
313
|
# SIGHUP will reload application code in the working
|
303
|
-
# directory/symlink when workers are gracefully restarted
|
314
|
+
# directory/symlink when workers are gracefully restarted when
|
315
|
+
# preload_app=false (the default). As reloading the application
|
316
|
+
# sometimes requires RubyGems updates, +Gem.refresh+ is always
|
317
|
+
# called before the application is loaded (for RubyGems users).
|
318
|
+
#
|
319
|
+
# During deployments, care should _always_ be taken to ensure your
|
320
|
+
# applications are properly deployed and running. Using
|
321
|
+
# preload_app=false (the default) means you _must_ check if
|
322
|
+
# your application is responding properly after a deployment.
|
323
|
+
# Improperly deployed applications can go into a spawn loop
|
324
|
+
# if the application fails to load. While your children are
|
325
|
+
# in a spawn loop, it is is possible to fix an application
|
326
|
+
# by properly deploying all required code and dependencies.
|
327
|
+
# Using preload_app=true means any application load error will
|
328
|
+
# cause the master process to exit with an error.
|
329
|
+
|
304
330
|
def preload_app(bool)
|
305
331
|
case bool
|
306
332
|
when TrueClass, FalseClass
|
@@ -333,9 +359,9 @@ module Unicorn
|
|
333
359
|
set_path(:stdout_path, path)
|
334
360
|
end
|
335
361
|
|
336
|
-
# sets the working directory for Unicorn. This ensures
|
362
|
+
# sets the working directory for Unicorn. This ensures SIGUSR2 will
|
337
363
|
# start a new instance of Unicorn in this directory. This may be
|
338
|
-
# a symlink.
|
364
|
+
# a symlink, a common scenario for Capistrano users.
|
339
365
|
def working_directory(path)
|
340
366
|
# just let chdir raise errors
|
341
367
|
path = File.expand_path(path)
|
@@ -411,5 +437,47 @@ module Unicorn
|
|
411
437
|
set[var] = my_proc
|
412
438
|
end
|
413
439
|
|
440
|
+
# this is called _after_ working_directory is bound. This only
|
441
|
+
# parses the embedded switches in .ru files
|
442
|
+
# (for "rackup" compatibility)
|
443
|
+
def parse_rackup_file # :nodoc:
|
444
|
+
ru = RACKUP[:file] or return # we only return here in unit tests
|
445
|
+
|
446
|
+
# :rails means use (old) Rails autodetect
|
447
|
+
if ru == :rails
|
448
|
+
File.readable?('config.ru') or return
|
449
|
+
ru = 'config.ru'
|
450
|
+
end
|
451
|
+
|
452
|
+
File.readable?(ru) or
|
453
|
+
raise ArgumentError, "rackup file (#{ru}) not readable"
|
454
|
+
|
455
|
+
# it could be a .rb file, too, we don't parse those manually
|
456
|
+
ru =~ /\.ru\z/ or return
|
457
|
+
|
458
|
+
/^#\\(.*)/ =~ File.read(ru) or return
|
459
|
+
RACKUP[:optparse].parse!($1.split(/\s+/))
|
460
|
+
|
461
|
+
# XXX ugly as hell, WILL FIX in 2.x (along with Rainbows!/Zbatery)
|
462
|
+
host, port, set_listener, options, daemonize =
|
463
|
+
eval("[ host, port, set_listener, options, daemonize ]",
|
464
|
+
TOPLEVEL_BINDING)
|
465
|
+
|
466
|
+
# XXX duplicate code from bin/unicorn{,_rails}
|
467
|
+
set[:listeners] << "#{host}:#{port}" if set_listener
|
468
|
+
|
469
|
+
if daemonize
|
470
|
+
# unicorn_rails wants a default pid path, (not plain 'unicorn')
|
471
|
+
if after_reload
|
472
|
+
spid = set[:pid]
|
473
|
+
pid('tmp/pids/unicorn.pid') if spid.nil? || spid == :unset
|
474
|
+
end
|
475
|
+
unless RACKUP[:daemonized]
|
476
|
+
Unicorn::Launcher.daemonize!(options)
|
477
|
+
RACKUP[:ready_pipe] = options.delete(:ready_pipe)
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
414
482
|
end
|
415
483
|
end
|
data/lib/unicorn/const.rb
CHANGED
@@ -8,8 +8,8 @@ module Unicorn
|
|
8
8
|
# Symbols did not really improve things much compared to constants.
|
9
9
|
module Const
|
10
10
|
|
11
|
-
# The current version of Unicorn, currently 0.
|
12
|
-
UNICORN_VERSION="0.
|
11
|
+
# The current version of Unicorn, currently 0.991.0
|
12
|
+
UNICORN_VERSION="0.991.0"
|
13
13
|
|
14
14
|
DEFAULT_HOST = "0.0.0.0" # default TCP listen host address
|
15
15
|
DEFAULT_PORT = 8080 # default TCP listen port
|
data/lib/unicorn/launcher.rb
CHANGED
@@ -19,47 +19,46 @@ class Unicorn::Launcher
|
|
19
19
|
# the directory it was started in when being re-executed
|
20
20
|
# to pickup code changes if the original deployment directory
|
21
21
|
# is a symlink or otherwise got replaced.
|
22
|
-
def self.daemonize!(options
|
22
|
+
def self.daemonize!(options)
|
23
23
|
$stdin.reopen("/dev/null")
|
24
24
|
|
25
25
|
# We only start a new process group if we're not being reexecuted
|
26
26
|
# and inheriting file descriptors from our parent
|
27
|
-
|
28
|
-
if
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
if ENV['UNICORN_FD']
|
28
|
+
exit if fork
|
29
|
+
Process.setsid
|
30
|
+
exit if fork
|
31
|
+
else
|
32
|
+
# grandparent - reads pipe, exits when master is ready
|
33
|
+
# \_ parent - exits immediately ASAP
|
34
|
+
# \_ unicorn master - writes to pipe when ready
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
rd, wr = IO.pipe
|
37
|
+
grandparent = $$
|
38
|
+
if fork
|
39
|
+
wr.close # grandparent does not write
|
40
|
+
else
|
41
|
+
rd.close # unicorn master does not read
|
42
|
+
Process.setsid
|
43
|
+
exit if fork # parent dies now
|
44
|
+
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
exit 0
|
51
|
-
else # unicorn master process
|
52
|
-
options[:ready_pipe] = wr
|
46
|
+
if grandparent == $$
|
47
|
+
# this will block until HttpServer#join runs (or it dies)
|
48
|
+
master_pid = (rd.readpartial(16) rescue nil).to_i
|
49
|
+
unless master_pid > 1
|
50
|
+
warn "master failed to start, check stderr log for details"
|
51
|
+
exit!(1)
|
53
52
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
exit if fork
|
53
|
+
exit 0
|
54
|
+
else # unicorn master process
|
55
|
+
options[:ready_pipe] = wr
|
58
56
|
end
|
59
|
-
# $stderr/$stderr can/will be redirected separately in the Unicorn config
|
60
|
-
Unicorn::Configurator::DEFAULTS[:stderr_path] = "/dev/null"
|
61
|
-
Unicorn::Configurator::DEFAULTS[:stdout_path] = "/dev/null"
|
62
57
|
end
|
58
|
+
# $stderr/$stderr can/will be redirected separately in the Unicorn config
|
59
|
+
Unicorn::Configurator::DEFAULTS[:stderr_path] ||= "/dev/null"
|
60
|
+
Unicorn::Configurator::DEFAULTS[:stdout_path] ||= "/dev/null"
|
61
|
+
Unicorn::Configurator::RACKUP[:daemonized] = true
|
63
62
|
end
|
64
63
|
|
65
64
|
end
|
data/t/my-tap-lib.sh
CHANGED
@@ -188,9 +188,10 @@ then
|
|
188
188
|
|
189
189
|
(
|
190
190
|
# use a subshell so seds are not waitable
|
191
|
-
$SED -e 's/^/#: /' $t_stdout &
|
192
|
-
$SED -e 's/^/#! /' $t_stderr &
|
191
|
+
$SED -e 's/^/#: /' < $t_stdout &
|
192
|
+
$SED -e 's/^/#! /' < $t_stderr &
|
193
193
|
) &
|
194
|
+
wait
|
194
195
|
exec > $t_stdout 2> $t_stderr
|
195
196
|
else
|
196
197
|
exec > /dev/null 2> /dev/null
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
if test -n "$RBX_SKIP"
|
3
|
+
then
|
4
|
+
echo "$0 is broken under Rubinius for now"
|
5
|
+
exit 0
|
6
|
+
fi
|
7
|
+
. ./test-lib.sh
|
8
|
+
|
9
|
+
t_plan 4 "config.ru inside alt working_directory"
|
10
|
+
|
11
|
+
t_begin "setup and start" && {
|
12
|
+
unicorn_setup
|
13
|
+
rtmpfiles unicorn_config_tmp
|
14
|
+
rm -rf $t_pfx.app
|
15
|
+
mkdir $t_pfx.app
|
16
|
+
|
17
|
+
cat > $t_pfx.app/config.ru <<EOF
|
18
|
+
#\--daemonize --host $host --port $port
|
19
|
+
use Rack::ContentLength
|
20
|
+
use Rack::ContentType, "text/plain"
|
21
|
+
run lambda { |env| [ 200, {}, [ "#{\$master_ppid}\\n" ] ] }
|
22
|
+
EOF
|
23
|
+
# we have --host/--port in config.ru instead
|
24
|
+
grep -v ^listen $unicorn_config > $unicorn_config_tmp
|
25
|
+
|
26
|
+
# the whole point of this exercise
|
27
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
|
28
|
+
|
29
|
+
# allows ppid to be 1 in before_fork
|
30
|
+
echo "preload_app true" >> $unicorn_config_tmp
|
31
|
+
cat >> $unicorn_config_tmp <<\EOF
|
32
|
+
before_fork do |server,worker|
|
33
|
+
$master_ppid = Process.ppid # should be zero to detect daemonization
|
34
|
+
end
|
35
|
+
EOF
|
36
|
+
|
37
|
+
mv $unicorn_config_tmp $unicorn_config
|
38
|
+
|
39
|
+
# rely on --daemonize switch, no & or -D
|
40
|
+
unicorn -c $unicorn_config
|
41
|
+
unicorn_wait_start
|
42
|
+
}
|
43
|
+
|
44
|
+
t_begin "hit with curl" && {
|
45
|
+
body=$(curl -sSf http://$listen/)
|
46
|
+
}
|
47
|
+
|
48
|
+
t_begin "killing succeeds" && {
|
49
|
+
kill $unicorn_pid
|
50
|
+
}
|
51
|
+
|
52
|
+
t_begin "response body ppid == 1 (daemonized)" && {
|
53
|
+
test "$body" -eq 1
|
54
|
+
}
|
55
|
+
|
56
|
+
t_done
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
|
4
|
+
t_plan 3 "config.ru is missing inside alt working_directory"
|
5
|
+
|
6
|
+
t_begin "setup" && {
|
7
|
+
unicorn_setup
|
8
|
+
rtmpfiles unicorn_config_tmp ok
|
9
|
+
rm -rf $t_pfx.app
|
10
|
+
mkdir $t_pfx.app
|
11
|
+
|
12
|
+
# the whole point of this exercise
|
13
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
|
14
|
+
}
|
15
|
+
|
16
|
+
t_begin "fails to start up w/o config.ru" && {
|
17
|
+
unicorn -c $unicorn_config_tmp || echo ok > $ok
|
18
|
+
}
|
19
|
+
|
20
|
+
t_begin "fallback code was run" && {
|
21
|
+
test x"$(cat $ok)" = xok
|
22
|
+
}
|
23
|
+
|
24
|
+
t_done
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
|
4
|
+
t_plan 4 "fooapp.rb inside alt working_directory"
|
5
|
+
|
6
|
+
t_begin "setup and start" && {
|
7
|
+
unicorn_setup
|
8
|
+
rm -rf $t_pfx.app
|
9
|
+
mkdir $t_pfx.app
|
10
|
+
|
11
|
+
cat > $t_pfx.app/fooapp.rb <<\EOF
|
12
|
+
class Fooapp
|
13
|
+
def self.call(env)
|
14
|
+
[ 200, [%w(Content-Type text/plain), %w(Content-Length 2)], %w(HI) ]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
EOF
|
18
|
+
# the whole point of this exercise
|
19
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config
|
20
|
+
cd /
|
21
|
+
unicorn -D -c $unicorn_config fooapp.rb
|
22
|
+
unicorn_wait_start
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "hit with curl" && {
|
26
|
+
body=$(curl -sSf http://$listen/)
|
27
|
+
}
|
28
|
+
|
29
|
+
t_begin "killing succeeds" && {
|
30
|
+
kill $unicorn_pid
|
31
|
+
}
|
32
|
+
|
33
|
+
t_begin "response body expected" && {
|
34
|
+
test x"$body" = xHI
|
35
|
+
}
|
36
|
+
|
37
|
+
t_done
|
data/t/t0300-rails3-basic.sh
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-rails3.sh
|
3
|
+
|
4
|
+
t_plan 3 "Rails 3 (beta) inside alt working_directory (no config.ru)"
|
5
|
+
|
6
|
+
t_begin "setup and start" && {
|
7
|
+
unicorn_setup
|
8
|
+
rails3_app=$(cd rails3-app && pwd)
|
9
|
+
rm -rf $t_pfx.app
|
10
|
+
mkdir $t_pfx.app
|
11
|
+
cd $t_pfx.app
|
12
|
+
( cd $rails3_app && tar cf - . ) | tar xf -
|
13
|
+
rm config.ru
|
14
|
+
$RAKE db:sessions:create
|
15
|
+
$RAKE db:migrate
|
16
|
+
unicorn_setup
|
17
|
+
rm $pid
|
18
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config
|
19
|
+
cd /
|
20
|
+
unicorn_rails -D -c $unicorn_config
|
21
|
+
unicorn_wait_start
|
22
|
+
}
|
23
|
+
|
24
|
+
t_begin "static file serving works" && {
|
25
|
+
test x"$(curl -sSf http://$listen/x.txt)" = xHELLO
|
26
|
+
}
|
27
|
+
|
28
|
+
t_begin "killing succeeds" && {
|
29
|
+
kill $unicorn_pid
|
30
|
+
}
|
31
|
+
|
32
|
+
t_done
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
if test -n "$RBX_SKIP"
|
3
|
+
then
|
4
|
+
echo "$0 is broken under Rubinius for now"
|
5
|
+
exit 0
|
6
|
+
fi
|
7
|
+
. ./test-rails3.sh
|
8
|
+
|
9
|
+
t_plan 5 "Rails 3 (beta) inside alt working_directory (w/ config.ru)"
|
10
|
+
|
11
|
+
t_begin "setup and start" && {
|
12
|
+
unicorn_setup
|
13
|
+
rtmpfiles unicorn_config_tmp usock
|
14
|
+
rm -f $usock
|
15
|
+
rails3_app=$(cd rails3-app && pwd)
|
16
|
+
rm -rf $t_pfx.app
|
17
|
+
mkdir $t_pfx.app
|
18
|
+
cd $t_pfx.app
|
19
|
+
( cd $rails3_app && tar cf - . ) | tar xf -
|
20
|
+
$RAKE db:sessions:create
|
21
|
+
$RAKE db:migrate
|
22
|
+
unicorn_setup
|
23
|
+
rm $pid
|
24
|
+
|
25
|
+
echo "#\\--daemonize --host $host --port $port -l $usock" \
|
26
|
+
>> $t_pfx.app/config.ru
|
27
|
+
|
28
|
+
# we have --host/--port in config.ru instead
|
29
|
+
grep -v ^listen $unicorn_config |
|
30
|
+
grep -v ^pid > $unicorn_config_tmp
|
31
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
|
32
|
+
cd /
|
33
|
+
unicorn_rails -c $unicorn_config_tmp
|
34
|
+
}
|
35
|
+
|
36
|
+
t_begin "pids in the right place" && {
|
37
|
+
if test -e $pid
|
38
|
+
then
|
39
|
+
die "pid=$pid not expected"
|
40
|
+
fi
|
41
|
+
|
42
|
+
unicorn_rails_pid="$t_pfx.app/tmp/pids/unicorn.pid"
|
43
|
+
unicorn_pid=$(cat $unicorn_rails_pid)
|
44
|
+
}
|
45
|
+
|
46
|
+
t_begin "static file serving works" && {
|
47
|
+
test x"$(curl -sSf http://$listen/x.txt)" = xHELLO
|
48
|
+
}
|
49
|
+
|
50
|
+
t_begin "socket created" && {
|
51
|
+
test -S $usock
|
52
|
+
}
|
53
|
+
|
54
|
+
t_begin "killing succeeds" && {
|
55
|
+
kill $unicorn_pid
|
56
|
+
}
|
57
|
+
|
58
|
+
t_done
|
data/t/test-lib.sh
CHANGED
@@ -4,6 +4,12 @@
|
|
4
4
|
. ./my-tap-lib.sh
|
5
5
|
|
6
6
|
set +u
|
7
|
+
|
8
|
+
# sometimes we rely on http_proxy to avoid wasting bandwidth with Isolate
|
9
|
+
# and multiple Ruby versions
|
10
|
+
NO_PROXY=${UNICORN_TEST_ADDR-127.0.0.1}
|
11
|
+
export NO_PROXY
|
12
|
+
|
7
13
|
set -e
|
8
14
|
RUBY="${RUBY-ruby}"
|
9
15
|
RUBY_VERSION=${RUBY_VERSION-$($RUBY -e 'puts RUBY_VERSION')}
|
@@ -76,6 +82,9 @@ check_stderr () {
|
|
76
82
|
# unicorn_setup
|
77
83
|
unicorn_setup () {
|
78
84
|
eval $(unused_listen)
|
85
|
+
port=$(expr $listen : '[^:]*:\([0-9]\+\)')
|
86
|
+
host=$(expr $listen : '\([^:]*\):[0-9]\+')
|
87
|
+
|
79
88
|
rtmpfiles unicorn_config pid r_err r_out fifo tmp ok
|
80
89
|
cat > $unicorn_config <<EOF
|
81
90
|
listen "$listen"
|
@@ -97,5 +106,5 @@ rsha1 () {
|
|
97
106
|
|
98
107
|
# last resort, see comments in sha1sum.rb for reasoning
|
99
108
|
test -n "$_cmd" || _cmd=sha1sum.rb
|
100
|
-
expr "$($_cmd
|
109
|
+
expr "$($_cmd)" : '\([a-f0-9]\{40\}\)'
|
101
110
|
}
|
data/t/test-rails3.sh
CHANGED
data/test/test_helper.rb
CHANGED
@@ -8,6 +8,9 @@
|
|
8
8
|
|
9
9
|
STDIN.sync = STDOUT.sync = STDERR.sync = true # buffering makes debugging hard
|
10
10
|
|
11
|
+
# FIXME: move curl-dependent tests into t/
|
12
|
+
ENV['NO_PROXY'] ||= ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
13
|
+
|
11
14
|
# Some tests watch a log file or a pid file to spring up to check state
|
12
15
|
# Can't rely on inotify on non-Linux and logging to a pipe makes things
|
13
16
|
# more complicated
|
data/unicorn.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
|
17
17
|
s.authors = ["Unicorn hackers"]
|
18
18
|
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
19
|
-
s.description = File.read("README").split(/\n\n/)[1]
|
19
|
+
s.description = File.read("README").split(/\n\n/)[1].delete('/')
|
20
20
|
s.email = %q{mongrel-unicorn@rubyforge.org}
|
21
21
|
s.executables = %w(unicorn unicorn_rails)
|
22
22
|
s.extensions = %w(ext/unicorn_http/extconf.rb)
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 3939
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 991
|
9
|
+
- 0
|
10
|
+
version: 0.991.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Unicorn hackers
|
@@ -9,35 +15,45 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-11 00:00:00 +00:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: rack
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
23
32
|
version: "0"
|
24
|
-
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
25
35
|
- !ruby/object:Gem::Dependency
|
26
36
|
name: isolate
|
27
|
-
|
28
|
-
|
29
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
30
40
|
requirements:
|
31
41
|
- - ~>
|
32
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 11
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 0
|
47
|
+
- 2
|
33
48
|
version: 2.0.2
|
34
|
-
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
35
51
|
description: |-
|
36
52
|
\Unicorn is an HTTP server for Rack applications designed to only serve
|
37
53
|
fast clients on low-latency, high-bandwidth connections and take
|
38
|
-
advantage of features in
|
54
|
+
advantage of features in UnixUnix-like kernels. Slow clients should
|
39
55
|
only be served by placing a reverse proxy capable of fully buffering
|
40
|
-
both the the request and response in between Unicorn and slow clients.
|
56
|
+
both the the request and response in between \Unicorn and slow clients.
|
41
57
|
email: mongrel-unicorn@rubyforge.org
|
42
58
|
executables:
|
43
59
|
- unicorn
|
@@ -187,8 +203,13 @@ files:
|
|
187
203
|
- t/t0000-http-basic.sh
|
188
204
|
- t/t0001-reload-bad-config.sh
|
189
205
|
- t/t0002-config-conflict.sh
|
206
|
+
- t/t0003-working_directory.sh
|
207
|
+
- t/t0004-working_directory_broken.sh
|
208
|
+
- t/t0005-working_directory_app.rb.sh
|
190
209
|
- t/t0300-rails3-basic.sh
|
191
210
|
- t/t0301-rails3-missing-config-ru.sh
|
211
|
+
- t/t0302-rails3-alt-working_directory.sh
|
212
|
+
- t/t0303-rails3-alt-working_directory_config.ru.sh
|
192
213
|
- t/test-lib.sh
|
193
214
|
- t/test-rails3.sh
|
194
215
|
- test/aggregate.rb
|
@@ -299,21 +320,27 @@ require_paths:
|
|
299
320
|
- lib
|
300
321
|
- ext
|
301
322
|
required_ruby_version: !ruby/object:Gem::Requirement
|
323
|
+
none: false
|
302
324
|
requirements:
|
303
325
|
- - ">="
|
304
326
|
- !ruby/object:Gem::Version
|
327
|
+
hash: 3
|
328
|
+
segments:
|
329
|
+
- 0
|
305
330
|
version: "0"
|
306
|
-
version:
|
307
331
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
332
|
+
none: false
|
308
333
|
requirements:
|
309
|
-
- - "
|
334
|
+
- - ">="
|
310
335
|
- !ruby/object:Gem::Version
|
311
|
-
|
312
|
-
|
336
|
+
hash: 3
|
337
|
+
segments:
|
338
|
+
- 0
|
339
|
+
version: "0"
|
313
340
|
requirements: []
|
314
341
|
|
315
342
|
rubyforge_project: mongrel
|
316
|
-
rubygems_version: 1.3.
|
343
|
+
rubygems_version: 1.3.7
|
317
344
|
signing_key:
|
318
345
|
specification_version: 3
|
319
346
|
summary: Rack HTTP server for fast clients and Unix
|