unicorn 0.8.0 → 0.8.1
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/CHANGELOG +1 -0
- data/README +8 -10
- data/Rakefile +2 -2
- data/SIGNALS +1 -3
- data/lib/unicorn.rb +29 -13
- data/lib/unicorn/const.rb +1 -1
- data/lib/unicorn/http_request.rb +3 -1
- data/unicorn.gemspec +5 -5
- metadata +5 -5
data/CHANGELOG
CHANGED
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Unicorn: Unix
|
1
|
+
= Unicorn: Rack HTTP server for Unix, fast clients and nothing else
|
2
2
|
|
3
3
|
== Features
|
4
4
|
|
@@ -81,9 +81,8 @@ You can get the latest source via git from the following locations
|
|
81
81
|
git://repo.or.cz/unicorn.git (mirror)
|
82
82
|
http://repo.or.cz/r/unicorn.git (mirror)
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
your web browser and download the latest snapshot tarballs here:
|
84
|
+
You may browse the code from the web and download the latest snapshot
|
85
|
+
tarballs here:
|
87
86
|
|
88
87
|
* http://git.bogomips.org/cgit/unicorn.git (cgit)
|
89
88
|
* http://repo.or.cz/w/unicorn.git (gitweb)
|
@@ -102,8 +101,8 @@ In RAILS_ROOT, run:
|
|
102
101
|
|
103
102
|
unicorn_rails
|
104
103
|
|
105
|
-
Unicorn will bind to all interfaces TCP port 8080 by default.
|
106
|
-
You may use the
|
104
|
+
Unicorn will bind to all interfaces on TCP port 8080 by default.
|
105
|
+
You may use the +--listen/-l+ switch to bind to a different
|
107
106
|
address:port or a UNIX socket.
|
108
107
|
|
109
108
|
=== Configuration File(s)
|
@@ -126,10 +125,9 @@ Like the creatures themselves, production deployments of Unicorn are
|
|
126
125
|
rare or even non-existent. There is NO WARRANTY whatsoever if anything
|
127
126
|
goes wrong, but let us know and we'll try our best to fix it.
|
128
127
|
|
129
|
-
Unicorn is designed to only serve fast clients
|
130
|
-
and DESIGN documents for more details
|
131
|
-
|
132
|
-
Rainbows are NOT included.
|
128
|
+
Unicorn is designed to only serve fast clients either on the local host
|
129
|
+
or a fast LAN. See the PHILOSOPHY and DESIGN documents for more details
|
130
|
+
regarding this.
|
133
131
|
|
134
132
|
== Known Issues
|
135
133
|
|
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require 'rubygems'
|
|
3
3
|
require 'echoe'
|
4
4
|
|
5
5
|
Echoe.new("unicorn") do |p|
|
6
|
-
p.summary = "
|
6
|
+
p.summary = "Rack HTTP server for Unix, fast clients and nothing else"
|
7
7
|
p.author = "Eric Wong"
|
8
8
|
p.email = "normalperson@yhbt.net"
|
9
9
|
p.clean_pattern = ['ext/unicorn/http11/*.{bundle,so,o,obj,pdb,lib,def,exp}',
|
@@ -12,7 +12,7 @@ Echoe.new("unicorn") do |p|
|
|
12
12
|
'pkg', 'lib/*.bundle', '*.gem',
|
13
13
|
'site/output', '.config', 'coverage',
|
14
14
|
'test_*.log', 'log', 'doc']
|
15
|
-
p.url = "http://unicorn.bogomips.org"
|
15
|
+
p.url = "http://unicorn.bogomips.org/"
|
16
16
|
p.ignore_pattern = /^(pkg|site|projects|doc|log)|CVS|\.log/
|
17
17
|
p.need_tar_gz = false
|
18
18
|
p.need_tgz = true
|
data/SIGNALS
CHANGED
@@ -6,9 +6,7 @@ processes are documented here as well.
|
|
6
6
|
|
7
7
|
=== Master Process
|
8
8
|
|
9
|
-
* HUP - reload config file and gracefully restart all workers
|
10
|
-
If "preload_app" is false (the default), the application code
|
11
|
-
will be reloaded when workers are restarted as well.
|
9
|
+
* HUP - reload config file, app, and gracefully restart all workers
|
12
10
|
|
13
11
|
* INT/TERM - quick shutdown, kills all workers immediately
|
14
12
|
|
data/lib/unicorn.rb
CHANGED
@@ -41,6 +41,9 @@ module Unicorn
|
|
41
41
|
# signal queue used for self-piping
|
42
42
|
SIG_QUEUE = []
|
43
43
|
|
44
|
+
# constant lookups are faster and we're single-threaded/non-reentrant
|
45
|
+
REQUEST = HttpRequest.new
|
46
|
+
|
44
47
|
# We populate this at startup so we can figure out how to reexecute
|
45
48
|
# and upgrade the currently running instance of Unicorn
|
46
49
|
START_CTX = {
|
@@ -71,7 +74,7 @@ module Unicorn
|
|
71
74
|
@config = Configurator.new(options.merge(:use_defaults => true))
|
72
75
|
@listener_opts = {}
|
73
76
|
@config.commit!(self, :skip => [:listeners, :pid])
|
74
|
-
@
|
77
|
+
@orig_app = app
|
75
78
|
end
|
76
79
|
|
77
80
|
# Runs the thing. Returns self so you can run join on it
|
@@ -141,6 +144,10 @@ module Unicorn
|
|
141
144
|
def stdout_path=(path); redirect_io($stdout, path); end
|
142
145
|
def stderr_path=(path); redirect_io($stderr, path); end
|
143
146
|
|
147
|
+
def logger=(obj)
|
148
|
+
REQUEST.logger = @logger = obj
|
149
|
+
end
|
150
|
+
|
144
151
|
# sets the path for the PID file of the master process
|
145
152
|
def pid=(path)
|
146
153
|
if path
|
@@ -310,8 +317,7 @@ module Unicorn
|
|
310
317
|
self.pid = @pid.chomp('.oldbin') if @pid
|
311
318
|
proc_name 'master'
|
312
319
|
else
|
313
|
-
worker = WORKERS.delete(pid)
|
314
|
-
worker.tempfile.close rescue nil
|
320
|
+
worker = WORKERS.delete(pid) and worker.tempfile.close rescue nil
|
315
321
|
logger.info "reaped #{status.inspect} " \
|
316
322
|
"worker=#{worker.nr rescue 'unknown'}"
|
317
323
|
end
|
@@ -377,13 +383,20 @@ module Unicorn
|
|
377
383
|
# is stale for >@timeout seconds, then we'll kill the corresponding
|
378
384
|
# worker.
|
379
385
|
def murder_lazy_workers
|
380
|
-
|
381
|
-
|
386
|
+
diff = stat = nil
|
387
|
+
WORKERS.dup.each_pair do |pid, worker|
|
388
|
+
stat = begin
|
389
|
+
worker.tempfile.stat
|
390
|
+
rescue => e
|
391
|
+
logger.warn "worker=#{worker.nr} PID:#{pid} stat error: #{e.inspect}"
|
392
|
+
kill_worker(:QUIT, pid)
|
393
|
+
next
|
394
|
+
end
|
382
395
|
stat.mode == 0100000 and next
|
383
|
-
Time.now - stat.ctime <= @timeout and next
|
384
|
-
logger.error "worker=#{worker.nr} PID:#{pid}
|
396
|
+
(diff = (Time.now - stat.ctime)) <= @timeout and next
|
397
|
+
logger.error "worker=#{worker.nr} PID:#{pid} timeout " \
|
398
|
+
"(#{diff}s > #{@timeout}s), killing"
|
385
399
|
kill_worker(:KILL, pid) # take no prisoners for @timeout violations
|
386
|
-
worker.tempfile.close rescue nil
|
387
400
|
end
|
388
401
|
end
|
389
402
|
|
@@ -409,15 +422,15 @@ module Unicorn
|
|
409
422
|
def maintain_worker_count
|
410
423
|
(off = WORKERS.size - @worker_processes) == 0 and return
|
411
424
|
off < 0 and return spawn_missing_workers
|
412
|
-
WORKERS.each_pair { |pid,w|
|
425
|
+
WORKERS.dup.each_pair { |pid,w|
|
413
426
|
w.nr >= @worker_processes and kill_worker(:QUIT, pid) rescue nil
|
414
427
|
}
|
415
428
|
end
|
416
429
|
|
417
430
|
# once a client is accepted, it is processed in its entirety here
|
418
431
|
# in 3 easy steps: read request, call app, write app response
|
419
|
-
def process_client(client)
|
420
|
-
HttpResponse.write(client,
|
432
|
+
def process_client(app, client)
|
433
|
+
HttpResponse.write(client, app.call(REQUEST.read(client)))
|
421
434
|
# if we get any error, try to write something back to the client
|
422
435
|
# assuming we haven't closed the socket, but don't get hung up
|
423
436
|
# if the socket is already closed or broken. We'll always ensure
|
@@ -452,7 +465,7 @@ module Unicorn
|
|
452
465
|
worker.tempfile.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
453
466
|
@after_fork.call(self, worker) # can drop perms
|
454
467
|
@timeout /= 2.0 # halve it for select()
|
455
|
-
build_app! unless @
|
468
|
+
build_app! unless @preload_app
|
456
469
|
end
|
457
470
|
|
458
471
|
def reopen_worker_logs(worker_nr)
|
@@ -478,6 +491,7 @@ module Unicorn
|
|
478
491
|
trap(:QUIT) { alive = nil; LISTENERS.each { |s| s.close rescue nil } }
|
479
492
|
[:TERM, :INT].each { |sig| trap(sig) { exit!(0) } } # instant shutdown
|
480
493
|
@logger.info "worker=#{worker.nr} ready"
|
494
|
+
app = @app
|
481
495
|
|
482
496
|
begin
|
483
497
|
nr < 0 and reopen_worker_logs(worker.nr)
|
@@ -495,7 +509,7 @@ module Unicorn
|
|
495
509
|
|
496
510
|
ready.each do |sock|
|
497
511
|
begin
|
498
|
-
process_client(sock.accept_nonblock)
|
512
|
+
process_client(app, sock.accept_nonblock)
|
499
513
|
nr += 1
|
500
514
|
t == (ti = Time.now.to_i) or alive.chmod(t = ti)
|
501
515
|
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
@@ -570,6 +584,8 @@ module Unicorn
|
|
570
584
|
@config.commit!(self)
|
571
585
|
kill_each_worker(:QUIT)
|
572
586
|
Unicorn::Util.reopen_logs
|
587
|
+
@app = @orig_app
|
588
|
+
build_app! if @preload_app
|
573
589
|
logger.info "done reloading config_file=#{@config.config_file}"
|
574
590
|
rescue Object => e
|
575
591
|
logger.error "error reloading config_file=#{@config.config_file}: " \
|
data/lib/unicorn/const.rb
CHANGED
@@ -5,7 +5,7 @@ module Unicorn
|
|
5
5
|
# gave about a 3% to 10% performance improvement over using the strings directly.
|
6
6
|
# Symbols did not really improve things much compared to constants.
|
7
7
|
module Const
|
8
|
-
UNICORN_VERSION="0.8.
|
8
|
+
UNICORN_VERSION="0.8.1".freeze
|
9
9
|
|
10
10
|
DEFAULT_HOST = "0.0.0.0".freeze # default TCP listen host address
|
11
11
|
DEFAULT_PORT = "8080".freeze # default TCP listen port
|
data/lib/unicorn/http_request.rb
CHANGED
@@ -12,6 +12,8 @@ module Unicorn
|
|
12
12
|
#
|
13
13
|
class HttpRequest
|
14
14
|
|
15
|
+
attr_accessor :logger
|
16
|
+
|
15
17
|
# default parameters we merge into the request env for Rack handlers
|
16
18
|
DEFAULTS = {
|
17
19
|
"rack.errors" => $stderr,
|
@@ -36,7 +38,7 @@ module Unicorn
|
|
36
38
|
PARSER = HttpParser.new
|
37
39
|
PARAMS = Hash.new
|
38
40
|
|
39
|
-
def initialize(logger)
|
41
|
+
def initialize(logger = Configurator::DEFAULT_LOGGER)
|
40
42
|
@logger = logger
|
41
43
|
end
|
42
44
|
|
data/unicorn.gemspec
CHANGED
@@ -2,24 +2,24 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{unicorn}
|
5
|
-
s.version = "0.8.
|
5
|
+
s.version = "0.8.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Eric Wong"]
|
9
|
-
s.date = %q{2009-05-
|
10
|
-
s.description = %q{
|
9
|
+
s.date = %q{2009-05-28}
|
10
|
+
s.description = %q{Rack HTTP server for Unix, fast clients and nothing else}
|
11
11
|
s.email = %q{normalperson@yhbt.net}
|
12
12
|
s.executables = ["unicorn", "unicorn_rails"]
|
13
13
|
s.extensions = ["ext/unicorn/http11/extconf.rb"]
|
14
14
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "TODO", "bin/unicorn", "bin/unicorn_rails", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb"]
|
15
15
|
s.files = [".document", ".gitignore", "CHANGELOG", "CONTRIBUTORS", "DESIGN", "GNUmakefile", "LICENSE", "Manifest", "PHILOSOPHY", "README", "Rakefile", "SIGNALS", "TODO", "TUNING", "bin/unicorn", "bin/unicorn_rails", "examples/init.sh", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb", "local.mk.sample", "setup.rb", "test/aggregate.rb", "test/benchmark/README", "test/benchmark/big_request.rb", "test/benchmark/dd.ru", "test/benchmark/request.rb", "test/benchmark/response.rb", "test/exec/README", "test/exec/test_exec.rb", "test/rails/app-1.2.3/.gitignore", "test/rails/app-1.2.3/Rakefile", "test/rails/app-1.2.3/app/controllers/application.rb", "test/rails/app-1.2.3/app/controllers/foo_controller.rb", "test/rails/app-1.2.3/app/helpers/application_helper.rb", "test/rails/app-1.2.3/config/boot.rb", "test/rails/app-1.2.3/config/database.yml", "test/rails/app-1.2.3/config/environment.rb", "test/rails/app-1.2.3/config/environments/development.rb", "test/rails/app-1.2.3/config/environments/production.rb", "test/rails/app-1.2.3/config/routes.rb", "test/rails/app-1.2.3/db/.gitignore", "test/rails/app-1.2.3/log/.gitignore", "test/rails/app-1.2.3/public/404.html", "test/rails/app-1.2.3/public/500.html", "test/rails/app-2.0.2/.gitignore", "test/rails/app-2.0.2/Rakefile", "test/rails/app-2.0.2/app/controllers/application.rb", "test/rails/app-2.0.2/app/controllers/foo_controller.rb", "test/rails/app-2.0.2/app/helpers/application_helper.rb", "test/rails/app-2.0.2/config/boot.rb", "test/rails/app-2.0.2/config/database.yml", "test/rails/app-2.0.2/config/environment.rb", "test/rails/app-2.0.2/config/environments/development.rb", "test/rails/app-2.0.2/config/environments/production.rb", "test/rails/app-2.0.2/config/routes.rb", "test/rails/app-2.0.2/db/.gitignore", "test/rails/app-2.0.2/log/.gitignore", "test/rails/app-2.0.2/public/404.html", "test/rails/app-2.0.2/public/500.html", "test/rails/app-2.1.2/.gitignore", "test/rails/app-2.1.2/Rakefile", "test/rails/app-2.1.2/app/controllers/application.rb", "test/rails/app-2.1.2/app/controllers/foo_controller.rb", "test/rails/app-2.1.2/app/helpers/application_helper.rb", "test/rails/app-2.1.2/config/boot.rb", "test/rails/app-2.1.2/config/database.yml", "test/rails/app-2.1.2/config/environment.rb", "test/rails/app-2.1.2/config/environments/development.rb", "test/rails/app-2.1.2/config/environments/production.rb", "test/rails/app-2.1.2/config/routes.rb", "test/rails/app-2.1.2/db/.gitignore", "test/rails/app-2.1.2/log/.gitignore", "test/rails/app-2.1.2/public/404.html", "test/rails/app-2.1.2/public/500.html", "test/rails/app-2.2.2/.gitignore", "test/rails/app-2.2.2/Rakefile", "test/rails/app-2.2.2/app/controllers/application.rb", "test/rails/app-2.2.2/app/controllers/foo_controller.rb", "test/rails/app-2.2.2/app/helpers/application_helper.rb", "test/rails/app-2.2.2/config/boot.rb", "test/rails/app-2.2.2/config/database.yml", "test/rails/app-2.2.2/config/environment.rb", "test/rails/app-2.2.2/config/environments/development.rb", "test/rails/app-2.2.2/config/environments/production.rb", "test/rails/app-2.2.2/config/routes.rb", "test/rails/app-2.2.2/db/.gitignore", "test/rails/app-2.2.2/log/.gitignore", "test/rails/app-2.2.2/public/404.html", "test/rails/app-2.2.2/public/500.html", "test/rails/app-2.3.2.1/.gitignore", "test/rails/app-2.3.2.1/Rakefile", "test/rails/app-2.3.2.1/app/controllers/application_controller.rb", "test/rails/app-2.3.2.1/app/controllers/foo_controller.rb", "test/rails/app-2.3.2.1/app/helpers/application_helper.rb", "test/rails/app-2.3.2.1/config/boot.rb", "test/rails/app-2.3.2.1/config/database.yml", "test/rails/app-2.3.2.1/config/environment.rb", "test/rails/app-2.3.2.1/config/environments/development.rb", "test/rails/app-2.3.2.1/config/environments/production.rb", "test/rails/app-2.3.2.1/config/routes.rb", "test/rails/app-2.3.2.1/db/.gitignore", "test/rails/app-2.3.2.1/log/.gitignore", "test/rails/app-2.3.2.1/public/404.html", "test/rails/app-2.3.2.1/public/500.html", "test/rails/test_rails.rb", "test/test_helper.rb", "test/unit/test_configurator.rb", "test/unit/test_http_parser.rb", "test/unit/test_request.rb", "test/unit/test_response.rb", "test/unit/test_server.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb", "test/unit/test_upload.rb", "test/unit/test_util.rb", "unicorn.gemspec"]
|
16
16
|
s.has_rdoc = true
|
17
|
-
s.homepage = %q{http://unicorn.bogomips.org}
|
17
|
+
s.homepage = %q{http://unicorn.bogomips.org/}
|
18
18
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Unicorn", "--main", "README"]
|
19
19
|
s.require_paths = ["lib", "ext"]
|
20
20
|
s.rubyforge_project = %q{unicorn}
|
21
21
|
s.rubygems_version = %q{1.3.2}
|
22
|
-
s.summary = %q{
|
22
|
+
s.summary = %q{Rack HTTP server for Unix, fast clients and nothing else}
|
23
23
|
s.test_files = ["test/unit/test_configurator.rb", "test/unit/test_response.rb", "test/unit/test_request.rb", "test/unit/test_signals.rb", "test/unit/test_upload.rb", "test/unit/test_http_parser.rb", "test/unit/test_socket_helper.rb", "test/unit/test_util.rb", "test/unit/test_server.rb"]
|
24
24
|
|
25
25
|
if s.respond_to? :specification_version then
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Wong
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-28 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,7 +22,7 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
|
-
description:
|
25
|
+
description: Rack HTTP server for Unix, fast clients and nothing else
|
26
26
|
email: normalperson@yhbt.net
|
27
27
|
executables:
|
28
28
|
- unicorn
|
@@ -188,7 +188,7 @@ files:
|
|
188
188
|
- test/unit/test_util.rb
|
189
189
|
- unicorn.gemspec
|
190
190
|
has_rdoc: true
|
191
|
-
homepage: http://unicorn.bogomips.org
|
191
|
+
homepage: http://unicorn.bogomips.org/
|
192
192
|
licenses: []
|
193
193
|
|
194
194
|
post_install_message:
|
@@ -220,7 +220,7 @@ rubyforge_project: unicorn
|
|
220
220
|
rubygems_version: 1.3.2
|
221
221
|
signing_key:
|
222
222
|
specification_version: 3
|
223
|
-
summary:
|
223
|
+
summary: Rack HTTP server for Unix, fast clients and nothing else
|
224
224
|
test_files:
|
225
225
|
- test/unit/test_configurator.rb
|
226
226
|
- test/unit/test_response.rb
|