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 CHANGED
@@ -1,3 +1,4 @@
1
+ *.o
1
2
  *.bundle
2
3
  *.log
3
4
  *.so
@@ -4,7 +4,7 @@
4
4
 
5
5
  # NAME
6
6
 
7
- unicorn_rails - a rackup-like command to launch the Unicorn HTTP server
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
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.96.1.GIT
4
+ DEF_VER=v0.97.0.GIT
5
5
 
6
6
  LF='
7
7
  '
@@ -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 = $(ruby)
13
- RAKE = $(rake)
14
- RAGEL = $(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.95.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
@@ -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 (steal from Rainbows!, probably...)
5
+ * improve test suite
@@ -108,52 +108,14 @@ opts = OptionParser.new("", 24, ' ') do |opts|
108
108
  opts.parse! ARGV
109
109
  end
110
110
 
111
- config = ARGV[0] || "config.ru"
112
- abort "configuration file #{config} not found" unless File.exist?(config)
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,
@@ -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
- if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
117
- opts.parse! $1.split(/\s+/)
118
- end
115
+ /^#\\(.*)/ =~ File.read(config) and opts.parse!($1.split(/\s+/))
119
116
  end
120
117
 
121
- require 'pp' if $DEBUG
122
-
123
- # this won't run until after forking if preload_app is false
124
- app = lambda do ||
125
- # Load Rails and the private version of Rack it bundles.
126
- begin
127
- require 'config/boot'
128
- rescue LoadError => err
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
- if old_rails
149
- require 'unicorn/app/old_rails'
150
- Unicorn::App::OldRails.new
151
- else
152
- ActionController::Dispatcher.new
153
- end
154
- when /\.ru$/
155
- raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
156
- raw.sub!(/^__END__\n.*/, '')
157
- eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
158
- else
159
- require config
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
- $stderr.puts "LogTailer not available for Rails < 2.3" unless daemonize
172
- $stderr.puts "Debugger not available" if $DEBUG
173
- map(map_path) do
174
- use Unicorn::App::OldRails::Static
175
- run inner_app
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
- use Rails::Rack::LogTailer unless daemonize
179
- use Rails::Rack::Debugger if $DEBUG
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
- end.to_app
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
- %w(cache pids sessions sockets).each do |dir|
200
- FileUtils.mkdir_p("tmp/#{dir}")
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] = rails_pid
201
+ options[:pid] = "tmp/pids/unicorn.pid"
205
202
  Unicorn::Launcher.daemonize!(options)
206
203
  end
207
204
  Unicorn.run(app, options)
@@ -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 $1 in
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"