unicorn 2.0.0pre3 → 2.0.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/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -2
- data/examples/unicorn.conf.rb +4 -1
- data/lib/unicorn/configurator.rb +15 -7
- data/lib/unicorn/const.rb +2 -2
- data/lib/unicorn/http_server.rb +20 -26
- data/t/t0012-reload-empty-config.sh +82 -0
- data/unicorn.gemspec +2 -2
- metadata +15 -17
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -175,7 +175,7 @@ NEWS: GIT-VERSION-FILE .manifest
|
|
175
175
|
$(RAKE) -s news_rdoc > $@+
|
176
176
|
mv $@+ $@
|
177
177
|
|
178
|
-
SINCE = 1.1.
|
178
|
+
SINCE = 1.1.5
|
179
179
|
ChangeLog: LOG_VERSION = \
|
180
180
|
$(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
|
181
181
|
echo $(GIT_VERSION) || git describe)
|
@@ -195,7 +195,7 @@ atom = <link rel="alternate" title="Atom feed" href="$(1)" \
|
|
195
195
|
doc: .document $(ext)/unicorn_http.c NEWS ChangeLog
|
196
196
|
for i in $(man1_rdoc); do echo > $$i; done
|
197
197
|
find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
198
|
-
rdoc -
|
198
|
+
rdoc -t "$(shell sed -ne '1s/^= //p' README)"
|
199
199
|
install -m644 COPYING doc/COPYING
|
200
200
|
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
201
201
|
$(MAKE) -C Documentation install-html install-man
|
data/examples/unicorn.conf.rb
CHANGED
@@ -63,7 +63,10 @@ before_fork do |server, worker|
|
|
63
63
|
# end
|
64
64
|
# end
|
65
65
|
#
|
66
|
-
#
|
66
|
+
# Throttle the master from forking too quickly by sleeping. Due
|
67
|
+
# to the implementation of standard Unix signal handlers, this
|
68
|
+
# helps (but does not completely) prevent identical, repeated signals
|
69
|
+
# from being lost when the receiving process is busy.
|
67
70
|
# sleep 1
|
68
71
|
end
|
69
72
|
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -8,7 +8,9 @@ require 'logger'
|
|
8
8
|
# example configuration files. An example config file for use with
|
9
9
|
# nginx is also available at
|
10
10
|
# http://unicorn.bogomips.org/examples/nginx.conf
|
11
|
-
class Unicorn::Configurator
|
11
|
+
class Unicorn::Configurator
|
12
|
+
attr_accessor :set, :config_file, :after_reload
|
13
|
+
|
12
14
|
# :stopdoc:
|
13
15
|
# used to stash stuff for deferred processing of cli options in
|
14
16
|
# config.ru after "working_directory" is bound. Do not rely on
|
@@ -42,21 +44,24 @@ class Unicorn::Configurator < Struct.new(:set, :config_file, :after_reload)
|
|
42
44
|
|
43
45
|
def initialize(defaults = {}) #:nodoc:
|
44
46
|
self.set = Hash.new(:unset)
|
45
|
-
use_defaults = defaults.delete(:use_defaults)
|
47
|
+
@use_defaults = defaults.delete(:use_defaults)
|
46
48
|
self.config_file = defaults.delete(:config_file)
|
47
49
|
|
48
50
|
# after_reload is only used by unicorn_rails, unsupported otherwise
|
49
51
|
self.after_reload = defaults.delete(:after_reload)
|
50
52
|
|
51
|
-
set.merge!(DEFAULTS) if use_defaults
|
52
|
-
defaults.each { |key, value| self.
|
53
|
+
set.merge!(DEFAULTS) if @use_defaults
|
54
|
+
defaults.each { |key, value| self.__send__(key, value) }
|
53
55
|
Hash === set[:listener_opts] or
|
54
56
|
set[:listener_opts] = Hash.new { |hash,key| hash[key] = {} }
|
55
57
|
Array === set[:listeners] or set[:listeners] = []
|
56
|
-
reload
|
58
|
+
reload(false)
|
57
59
|
end
|
58
60
|
|
59
|
-
def reload #:nodoc:
|
61
|
+
def reload(merge_defaults = true) #:nodoc:
|
62
|
+
if merge_defaults && @use_defaults
|
63
|
+
set.merge!(DEFAULTS) if @use_defaults
|
64
|
+
end
|
60
65
|
instance_eval(File.read(config_file), config_file) if config_file
|
61
66
|
|
62
67
|
parse_rackup_file
|
@@ -401,7 +406,10 @@ class Unicorn::Configurator < Struct.new(:set, :config_file, :after_reload)
|
|
401
406
|
|
402
407
|
# sets the working directory for Unicorn. This ensures SIGUSR2 will
|
403
408
|
# start a new instance of Unicorn in this directory. This may be
|
404
|
-
# a symlink, a common scenario for Capistrano users.
|
409
|
+
# a symlink, a common scenario for Capistrano users. Unlike
|
410
|
+
# all other Unicorn configuration directives, this binds immediately
|
411
|
+
# for error checking and cannot be undone by unsetting it in the
|
412
|
+
# configuration file and reloading.
|
405
413
|
def working_directory(path)
|
406
414
|
# just let chdir raise errors
|
407
415
|
path = File.expand_path(path)
|
data/lib/unicorn/const.rb
CHANGED
@@ -7,8 +7,8 @@
|
|
7
7
|
# improve things much compared to constants.
|
8
8
|
module Unicorn::Const
|
9
9
|
|
10
|
-
# The current version of Unicorn, currently 2.0.
|
11
|
-
UNICORN_VERSION = "2.0.
|
10
|
+
# The current version of Unicorn, currently 2.0.0
|
11
|
+
UNICORN_VERSION = "2.0.0"
|
12
12
|
|
13
13
|
# default TCP listen host address (0.0.0.0, all interfaces)
|
14
14
|
DEFAULT_HOST = "0.0.0.0"
|
data/lib/unicorn/http_server.rb
CHANGED
@@ -50,6 +50,10 @@ class Unicorn::HttpServer
|
|
50
50
|
# signal queue used for self-piping
|
51
51
|
SIG_QUEUE = []
|
52
52
|
|
53
|
+
# list of signals we care about and trap in master.
|
54
|
+
QUEUE_SIGS = [ :WINCH, :QUIT, :INT, :TERM, :USR1, :USR2, :HUP, :TTIN, :TTOU ]
|
55
|
+
|
56
|
+
# :startdoc:
|
53
57
|
# We populate this at startup so we can figure out how to reexecute
|
54
58
|
# and upgrade the currently running instance of Unicorn
|
55
59
|
# This Hash is considered a stable interface and changing its contents
|
@@ -82,7 +86,6 @@ class Unicorn::HttpServer
|
|
82
86
|
}.call,
|
83
87
|
0 => $0.dup,
|
84
88
|
}
|
85
|
-
# :startdoc:
|
86
89
|
|
87
90
|
# Creates a working server on host:port (strange things happen if
|
88
91
|
# port isn't a Number). Use HttpServer::run to start the server and
|
@@ -151,8 +154,8 @@ class Unicorn::HttpServer
|
|
151
154
|
# setup signal handlers before writing pid file in case people get
|
152
155
|
# trigger happy and send signals as soon as the pid file exists.
|
153
156
|
# Note that signals don't actually get handled until the #join method
|
154
|
-
QUEUE_SIGS.each { |sig|
|
155
|
-
trap(:CHLD) {
|
157
|
+
QUEUE_SIGS.each { |sig| trap(sig) { SIG_QUEUE << sig; awaken_master } }
|
158
|
+
trap(:CHLD) { awaken_master }
|
156
159
|
self.pid = config[:pid]
|
157
160
|
|
158
161
|
self.master_pid = $$
|
@@ -287,14 +290,14 @@ class Unicorn::HttpServer
|
|
287
290
|
when nil
|
288
291
|
# avoid murdering workers after our master process (or the
|
289
292
|
# machine) comes out of suspend/hibernation
|
290
|
-
if (last_check + timeout) >= (last_check = Time.now)
|
291
|
-
murder_lazy_workers
|
293
|
+
if (last_check + @timeout) >= (last_check = Time.now)
|
294
|
+
sleep_time = murder_lazy_workers
|
292
295
|
else
|
293
296
|
# wait for workers to wakeup on suspend
|
294
|
-
|
297
|
+
sleep_time = @timeout/2.0 + 1
|
295
298
|
end
|
296
299
|
maintain_worker_count if respawn
|
297
|
-
master_sleep(
|
300
|
+
master_sleep(sleep_time)
|
298
301
|
when :QUIT # graceful shutdown
|
299
302
|
break
|
300
303
|
when :TERM, :INT # immediate shutdown
|
@@ -354,24 +357,7 @@ class Unicorn::HttpServer
|
|
354
357
|
|
355
358
|
private
|
356
359
|
|
357
|
-
# list of signals we care about and trap in master.
|
358
|
-
QUEUE_SIGS = [ :WINCH, :QUIT, :INT, :TERM, :USR1, :USR2, :HUP,
|
359
|
-
:TTIN, :TTOU ]
|
360
|
-
|
361
|
-
# defer a signal for later processing in #join (master process)
|
362
|
-
def trap_deferred(signal)
|
363
|
-
trap(signal) do |sig_nr|
|
364
|
-
if SIG_QUEUE.size < 5
|
365
|
-
SIG_QUEUE << signal
|
366
|
-
awaken_master
|
367
|
-
else
|
368
|
-
logger.error "ignoring SIG#{signal}, queue=#{SIG_QUEUE.inspect}"
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
360
|
# wait for a signal hander to wake us up and then consume the pipe
|
374
|
-
# Wake up every second anyways to run murder_lazy_workers
|
375
361
|
def master_sleep(sec)
|
376
362
|
IO.select([ SELF_PIPE[0] ], nil, nil, sec) or return
|
377
363
|
SELF_PIPE[0].kgio_tryread(11)
|
@@ -457,15 +443,23 @@ class Unicorn::HttpServer
|
|
457
443
|
# is stale for >timeout seconds, then we'll kill the corresponding
|
458
444
|
# worker.
|
459
445
|
def murder_lazy_workers
|
446
|
+
t = @timeout
|
447
|
+
next_sleep = 1
|
460
448
|
WORKERS.dup.each_pair do |wpid, worker|
|
461
449
|
stat = worker.tmp.stat
|
462
450
|
# skip workers that disable fchmod or have never fchmod-ed
|
463
451
|
stat.mode == 0100600 and next
|
464
|
-
|
452
|
+
diff = Time.now - stat.ctime
|
453
|
+
if diff <= t
|
454
|
+
tmp = t - diff
|
455
|
+
next_sleep < tmp and next_sleep = tmp
|
456
|
+
next
|
457
|
+
end
|
465
458
|
logger.error "worker=#{worker.nr} PID:#{wpid} timeout " \
|
466
|
-
"(#{diff}s > #{
|
459
|
+
"(#{diff}s > #{t}s), killing"
|
467
460
|
kill_worker(:KILL, wpid) # take no prisoners for timeout violations
|
468
461
|
end
|
462
|
+
next_sleep
|
469
463
|
end
|
470
464
|
|
471
465
|
def spawn_missing_workers
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 9 "reloading unset config resets defaults"
|
4
|
+
|
5
|
+
t_begin "setup and start" && {
|
6
|
+
unicorn_setup
|
7
|
+
rtmpfiles unicorn_config_orig before_reload after_reload
|
8
|
+
cat $unicorn_config > $unicorn_config_orig
|
9
|
+
cat >> $unicorn_config <<EOF
|
10
|
+
logger Logger.new(STDOUT)
|
11
|
+
preload_app true
|
12
|
+
timeout 0x7fffffff
|
13
|
+
worker_processes 2
|
14
|
+
after_fork { |s,w| }
|
15
|
+
\$dump_cfg = lambda { |fp,srv|
|
16
|
+
defaults = Unicorn::Configurator::DEFAULTS
|
17
|
+
defaults.keys.map { |x| x.to_s }.sort.each do |key|
|
18
|
+
next if key =~ %r{\Astd(?:err|out)_path\z}
|
19
|
+
key = key.to_sym
|
20
|
+
def_value = defaults[key]
|
21
|
+
srv_value = srv.__send__(key)
|
22
|
+
fp << "#{key}|#{srv_value}|#{def_value}\\n"
|
23
|
+
end
|
24
|
+
}
|
25
|
+
before_fork { |s,w|
|
26
|
+
File.open("$before_reload", "a") { |fp| \$dump_cfg.call(fp, s) }
|
27
|
+
}
|
28
|
+
before_exec { |s| }
|
29
|
+
EOF
|
30
|
+
unicorn -D -c $unicorn_config env.ru
|
31
|
+
unicorn_wait_start
|
32
|
+
}
|
33
|
+
|
34
|
+
t_begin "ensure worker is started" && {
|
35
|
+
curl -sSf http://$listen/ > $tmp
|
36
|
+
}
|
37
|
+
|
38
|
+
t_begin "replace config file with original(-ish)" && {
|
39
|
+
grep -v ^pid < $unicorn_config_orig > $unicorn_config
|
40
|
+
cat >> $unicorn_config <<EOF
|
41
|
+
before_fork { |s,w|
|
42
|
+
File.open("$after_reload", "a") { |fp| \$dump_cfg.call(fp, s) }
|
43
|
+
}
|
44
|
+
EOF
|
45
|
+
}
|
46
|
+
|
47
|
+
t_begin "reload signal succeeds" && {
|
48
|
+
kill -HUP $unicorn_pid
|
49
|
+
while ! egrep '(done|error) reloading' $r_err >/dev/null
|
50
|
+
do
|
51
|
+
sleep 1
|
52
|
+
done
|
53
|
+
|
54
|
+
grep 'done reloading' $r_err >/dev/null
|
55
|
+
}
|
56
|
+
|
57
|
+
t_begin "ensure worker is started" && {
|
58
|
+
curl -sSf http://$listen/ > $tmp
|
59
|
+
}
|
60
|
+
|
61
|
+
t_begin "pid file no longer exists" && {
|
62
|
+
if test -f $pid
|
63
|
+
then
|
64
|
+
die "pid=$pid should not exist"
|
65
|
+
fi
|
66
|
+
}
|
67
|
+
|
68
|
+
t_begin "killing succeeds" && {
|
69
|
+
kill $unicorn_pid
|
70
|
+
}
|
71
|
+
|
72
|
+
t_begin "check stderr" && {
|
73
|
+
check_stderr
|
74
|
+
}
|
75
|
+
|
76
|
+
t_begin "ensure reloading restored settings" && {
|
77
|
+
awk < $after_reload -F'|' '
|
78
|
+
$1 != "before_fork" && $2 != $3 { print $0; exit(1) }
|
79
|
+
'
|
80
|
+
}
|
81
|
+
|
82
|
+
t_done
|
data/unicorn.gemspec
CHANGED
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
|
|
36
36
|
s.homepage = %q{http://unicorn.bogomips.org/}
|
37
37
|
|
38
38
|
summary = %q{Rack HTTP server for fast clients and Unix}
|
39
|
-
s.rdoc_options = [ "-
|
39
|
+
s.rdoc_options = [ "-t", "Unicorn: #{summary}" ]
|
40
40
|
s.require_paths = %w(lib ext)
|
41
41
|
s.rubyforge_project = %q{mongrel}
|
42
42
|
s.summary = summary
|
@@ -50,7 +50,7 @@ Gem::Specification.new do |s|
|
|
50
50
|
s.add_dependency(%q<rack>)
|
51
51
|
s.add_dependency(%q<kgio>, '~> 1.3.1')
|
52
52
|
|
53
|
-
s.add_development_dependency('isolate', '~>
|
53
|
+
s.add_development_dependency('isolate', '~> 3.0.0')
|
54
54
|
|
55
55
|
# s.licenses = %w(GPLv2 Ruby) # licenses= method is not in older RubyGems
|
56
56
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 2.0.
|
9
|
+
- 0
|
10
|
+
version: 2.0.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Unicorn hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-27 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -56,12 +56,12 @@ dependencies:
|
|
56
56
|
requirements:
|
57
57
|
- - ~>
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
hash:
|
59
|
+
hash: 7
|
60
60
|
segments:
|
61
|
-
-
|
62
|
-
-
|
63
|
-
-
|
64
|
-
version:
|
61
|
+
- 3
|
62
|
+
- 0
|
63
|
+
- 0
|
64
|
+
version: 3.0.0
|
65
65
|
type: :development
|
66
66
|
version_requirements: *id003
|
67
67
|
description: |-
|
@@ -240,6 +240,7 @@ files:
|
|
240
240
|
- t/t0009-winch_ttin.sh
|
241
241
|
- t/t0010-reap-logging.sh
|
242
242
|
- t/t0011-active-unix-socket.sh
|
243
|
+
- t/t0012-reload-empty-config.sh
|
243
244
|
- t/t0300-rails3-basic.sh
|
244
245
|
- t/t0301-rails3-missing-config-ru.sh
|
245
246
|
- t/t0302-rails3-alt-working_directory.sh
|
@@ -349,7 +350,6 @@ licenses: []
|
|
349
350
|
|
350
351
|
post_install_message:
|
351
352
|
rdoc_options:
|
352
|
-
- -Na
|
353
353
|
- -t
|
354
354
|
- "Unicorn: Rack HTTP server for fast clients and Unix"
|
355
355
|
require_paths:
|
@@ -367,14 +367,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
367
367
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
368
368
|
none: false
|
369
369
|
requirements:
|
370
|
-
- - "
|
370
|
+
- - ">="
|
371
371
|
- !ruby/object:Gem::Version
|
372
|
-
hash:
|
372
|
+
hash: 3
|
373
373
|
segments:
|
374
|
-
-
|
375
|
-
|
376
|
-
- 1
|
377
|
-
version: 1.3.1
|
374
|
+
- 0
|
375
|
+
version: "0"
|
378
376
|
requirements: []
|
379
377
|
|
380
378
|
rubyforge_project: mongrel
|