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 CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.990.0.GIT
4
+ DEF_VER=v0.991.0.GIT
5
5
 
6
6
  LF='
7
7
  '
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.99.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
- else
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/ruby-#{RUBY_VERSION}",
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.beta3).each do |rails_ver|
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
- ru = ARGV[0] || "config.ru"
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
- $stderr.puts "relative URL roots may not work for older Rails"
166
+ warn "relative URL roots may not work for older Rails"
158
167
  end
159
- $stderr.puts "LogTailer not available for Rails < 2.3" unless daemonize
160
- $stderr.puts "Debugger not available" if $DEBUG
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
- if defined?(ActionDispatch::Static)
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 = ru ? Unicorn.builder(ru, opts) : rails_builder(daemonize)
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 && exit 0
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
  ;;
@@ -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
- # define rb_str_set_len(str,len) rb_str_resize(str,len)
19
- # else /* 1.8.6 optimized version */
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) */
@@ -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
- # -fPIC is needed for Rubinius, MRI already uses it regardless
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
- if ru =~ /\.ru\z/
37
- # parse embedded command-line options in config.ru comments
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$/
@@ -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 USR2 will
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.990.0
12
- UNICORN_VERSION="0.990.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
@@ -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 = nil)
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
- unless ENV['UNICORN_FD']
28
- if options
29
- # grandparent - reads pipe, exits when master is ready
30
- # \_ parent - exits immediately ASAP
31
- # \_ unicorn master - writes to pipe when ready
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
- rd, wr = IO.pipe
34
- grandparent = $$
35
- if fork
36
- wr.close # grandparent does not write
37
- else
38
- rd.close # unicorn master does not read
39
- Process.setsid
40
- exit if fork # parent dies now
41
- end
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
- if grandparent == $$
44
- # this will block until HttpServer#join runs (or it dies)
45
- master_pid = (rd.readpartial(16) rescue nil).to_i
46
- unless master_pid > 1
47
- warn "master failed to start, check stderr log for details"
48
- exit!(1)
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
- else # backwards compat
55
- exit if fork
56
- Process.setsid
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
@@ -18,7 +18,7 @@ t_begin "setup and start" && {
18
18
 
19
19
  # add more tests here
20
20
  t_begin "hit with curl" && {
21
- curl -v http://$listen/ || :
21
+ test xHELLO = x"$(curl -sSf http://$listen/x.txt)"
22
22
  }
23
23
 
24
24
  t_begin "killing succeeds" && {
@@ -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 < random_blob)" : '\([a-f0-9]\{40\}\)'
109
+ expr "$($_cmd)" : '\([a-f0-9]\{40\}\)'
101
110
  }
data/t/test-rails3.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  . ./test-lib.sh
2
- RAILS_VERSION=${RAILS_VERSION-3.0.0.beta3}
2
+ RAILS_VERSION=${RAILS_VERSION-3.0.0.beta4}
3
3
  case $RUBY_VERSION in
4
4
  1.8.7|1.9.2) ;;
5
5
  *)
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
- version: 0.990.0.5.gbfb1
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-08 00:00:00 +00:00
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
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
33
+ type: :runtime
34
+ version_requirements: *id001
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: isolate
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
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 Unix/Unix-like kernels. Slow clients should
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
- version: 1.3.1
312
- version:
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.5
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