diff options
-rw-r--r-- | lib/unicorn/configurator.rb | 16 | ||||
-rwxr-xr-x | t/t0012-reload-empty-config.sh | 82 |
2 files changed, 93 insertions, 5 deletions
diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index 9355c66..dd515a7 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -44,21 +44,24 @@ class Unicorn::Configurator def initialize(defaults = {}) #:nodoc: self.set = Hash.new(:unset) - use_defaults = defaults.delete(:use_defaults) + @use_defaults = defaults.delete(:use_defaults) self.config_file = defaults.delete(:config_file) # after_reload is only used by unicorn_rails, unsupported otherwise self.after_reload = defaults.delete(:after_reload) - set.merge!(DEFAULTS) if use_defaults + set.merge!(DEFAULTS) if @use_defaults defaults.each { |key, value| self.__send__(key, value) } Hash === set[:listener_opts] or set[:listener_opts] = Hash.new { |hash,key| hash[key] = {} } Array === set[:listeners] or set[:listeners] = [] - reload + reload(false) end - def reload #:nodoc: + def reload(merge_defaults = true) #:nodoc: + if merge_defaults && @use_defaults + set.merge!(DEFAULTS) if @use_defaults + end instance_eval(File.read(config_file), config_file) if config_file parse_rackup_file @@ -403,7 +406,10 @@ class Unicorn::Configurator # sets the working directory for Unicorn. This ensures SIGUSR2 will # start a new instance of Unicorn in this directory. This may be - # a symlink, a common scenario for Capistrano users. + # a symlink, a common scenario for Capistrano users. Unlike + # all other Unicorn configuration directives, this binds immediately + # for error checking and cannot be undone by unsetting it in the + # configuration file and reloading. def working_directory(path) # just let chdir raise errors path = File.expand_path(path) diff --git a/t/t0012-reload-empty-config.sh b/t/t0012-reload-empty-config.sh new file mode 100755 index 0000000..c18c030 --- /dev/null +++ b/t/t0012-reload-empty-config.sh @@ -0,0 +1,82 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 9 "reloading unset config resets defaults" + +t_begin "setup and start" && { + unicorn_setup + rtmpfiles unicorn_config_orig before_reload after_reload + cat $unicorn_config > $unicorn_config_orig + cat >> $unicorn_config <<EOF +logger Logger.new(STDOUT) +preload_app true +timeout 0x7fffffff +worker_processes 2 +after_fork { |s,w| } +\$dump_cfg = lambda { |fp,srv| + defaults = Unicorn::Configurator::DEFAULTS + defaults.keys.map { |x| x.to_s }.sort.each do |key| + next if key =~ %r{\Astd(?:err|out)_path\z} + key = key.to_sym + def_value = defaults[key] + srv_value = srv.__send__(key) + fp << "#{key}|#{srv_value}|#{def_value}\\n" + end +} +before_fork { |s,w| + File.open("$before_reload", "a") { |fp| \$dump_cfg.call(fp, s) } +} +before_exec { |s| } +EOF + unicorn -D -c $unicorn_config env.ru + unicorn_wait_start +} + +t_begin "ensure worker is started" && { + curl -sSf http://$listen/ > $tmp +} + +t_begin "replace config file with original(-ish)" && { + grep -v ^pid < $unicorn_config_orig > $unicorn_config + cat >> $unicorn_config <<EOF +before_fork { |s,w| + File.open("$after_reload", "a") { |fp| \$dump_cfg.call(fp, s) } +} +EOF +} + +t_begin "reload signal succeeds" && { + kill -HUP $unicorn_pid + while ! egrep '(done|error) reloading' $r_err >/dev/null + do + sleep 1 + done + + grep 'done reloading' $r_err >/dev/null +} + +t_begin "ensure worker is started" && { + curl -sSf http://$listen/ > $tmp +} + +t_begin "pid file no longer exists" && { + if test -f $pid + then + die "pid=$pid should not exist" + fi +} + +t_begin "killing succeeds" && { + kill $unicorn_pid +} + +t_begin "check stderr" && { + check_stderr +} + +t_begin "ensure reloading restored settings" && { + awk < $after_reload -F'|' ' +$1 != "before_fork" && $2 != $3 { print $0; exit(1) } +' +} + +t_done |