From 5a0506c2affd2f5abe6e7315121e67aa3e32b253 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 16 Jul 2010 08:25:32 +0000 Subject: SIGTTIN works after SIGWINCH In addition to SIGHUP, it should be possible to gradually bring workers back up (to avoid overloading the machine) when rolling back upgrades after SIGWINCH. Noticed-by: Lawrence Pit ref: http://mid.gmane.org/4C3F8C9F.2090903@gmail.com (cherry picked from commit e75ee7615f9875db314a6403964e7b69a68b0521) --- lib/unicorn.rb | 2 ++ t/t0009-winch_ttin.sh | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100755 t/t0009-winch_ttin.sh diff --git a/lib/unicorn.rb b/lib/unicorn.rb index cbb5520..e2d1ac1 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -422,10 +422,12 @@ module Unicorn respawn = false logger.info "gracefully stopping all workers" kill_each_worker(:QUIT) + self.worker_processes = 0 else logger.info "SIGWINCH ignored because we're not daemonized" end when :TTIN + respawn = true self.worker_processes += 1 when :TTOU self.worker_processes -= 1 if self.worker_processes > 0 diff --git a/t/t0009-winch_ttin.sh b/t/t0009-winch_ttin.sh new file mode 100755 index 0000000..6e56e30 --- /dev/null +++ b/t/t0009-winch_ttin.sh @@ -0,0 +1,59 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 8 "SIGTTIN succeeds after SIGWINCH" + +t_begin "setup and start" && { + unicorn_setup +cat >> $unicorn_config </dev/null + do + i=$(( $i + 1 )) + test $i -lt 600 || die "timed out" + sleep 1 + done +} + +t_begin "start one worker back up" && { + kill -TTIN $unicorn_pid +} + +t_begin "wait for new worker to start" && { + test 0 -eq $(cat $fifo) || die "worker.nr != 0" + new_worker_pid=$(curl -sSf http://$listen/) + test -n "$new_worker_pid" && kill -0 $new_worker_pid + test $orig_worker_pid -ne $new_worker_pid || \ + die "worker wasn't replaced" +} + +t_begin "killing succeeds" && { + kill $unicorn_pid +} + +t_begin "check stderr" && check_stderr + +dbgcat r_err + +t_done -- cgit v1.2.3-24-ge0c7 From 10037f2aabb3fab4296fc90c615e7caa9f4a9b53 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 01:44:33 +0000 Subject: fix delays in signal handling There is no need to loop in the master_sleep method at all, as the rest of the code is designed to function even on interrupted sleeps. This change is included as part of a larger cleanup in master. (commit bdc79712e5ac53d39c51e80dfe50aff950e5053f) --- lib/unicorn.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/unicorn.rb b/lib/unicorn.rb index e2d1ac1..f454eb7 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -488,12 +488,9 @@ module Unicorn # wait for a signal hander to wake us up and then consume the pipe # Wake up every second anyways to run murder_lazy_workers def master_sleep(sec) - begin - IO.select([ SELF_PIPE.first ], nil, nil, sec) or return - SELF_PIPE.first.read_nonblock(Const::CHUNK_SIZE, HttpRequest::BUF) + IO.select([ SELF_PIPE[0] ], nil, nil, sec) or return + SELF_PIPE[0].read_nonblock(Const::CHUNK_SIZE, HttpRequest::BUF) rescue Errno::EAGAIN, Errno::EINTR - break - end while true end def awaken_master -- cgit v1.2.3-24-ge0c7 From 74dec350d93b88c0a5bd792239671097901e2393 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 19:32:55 +0000 Subject: Rakefile: don't post freshmeat on empty changelogs We don't want to flood or monopolize freshmeat. (cherry picked from commit 1ad510d645e0c84c8d352ac0deaeefa75240ea94) --- Rakefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 69f922e..ec427b3 100644 --- a/Rakefile +++ b/Rakefile @@ -168,8 +168,12 @@ task :fm_update do "changelog" => changelog, }, }.to_json - Net::HTTP.start(uri.host, uri.port) do |http| - p http.post(uri.path, req, {'Content-Type'=>'application/json'}) + if ! changelog.strip.empty? && version =~ %r{\A[\d\.]+\d+\z} + Net::HTTP.start(uri.host, uri.port) do |http| + p http.post(uri.path, req, {'Content-Type'=>'application/json'}) + end + else + warn "not updating freshmeat for v#{version}" end end -- cgit v1.2.3-24-ge0c7 From 928a88d5419210380078a2e141cb64d308719295 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 6 Oct 2010 01:27:45 +0000 Subject: Rakefile: capture prerelease tags Since we do those, now. (cherry picked from commit 1d1a2b1bd5bdd89f774f19bf8ad24c2f5f8a2d4c) --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index ec427b3..b680df6 100644 --- a/Rakefile +++ b/Rakefile @@ -15,7 +15,7 @@ def tags timefmt = '%Y-%m-%dT%H:%M:%SZ' @tags ||= `git tag -l`.split(/\n/).map do |tag| next if tag == "v0.0.0" - if %r{\Av[\d\.]+\z} =~ tag + if %r{\Av[\d\.]+} =~ tag header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3) header = header.split(/\n/) tagger = header.grep(/\Atagger /).first -- cgit v1.2.3-24-ge0c7 From 5e672c48d8a3555e4a01f653fb2e0b3556087737 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 12:46:46 -0700 Subject: configurator: use "__send__" instead of "send" It's less ambiguous since this is a network server after all. (cherry picked from commit f62c5850d7d17d7b5e301a494f8bdf5be3674411) --- lib/unicorn/configurator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index 533e0ed..a927ed8 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -47,7 +47,7 @@ module Unicorn self.after_reload = defaults.delete(:after_reload) set.merge!(DEFAULTS) if use_defaults - defaults.each { |key, value| self.send(key, value) } + 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] = [] -- cgit v1.2.3-24-ge0c7 From 2dd4a89d5726e13b962c1e287d84a6c30f5dd46c Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 13:51:12 -0700 Subject: configurator: reloading with unset values restores default If a configuration directive is set at startup and later unset, it correctly restores the original default value as if it had never been set in the first place. This applies to the majority of the configuration values with a few exceptions: * This only applies to stderr_path and stdout_path when daemonized (the usual case, they'll be redirected to "/dev/null"). When NOT daemonized, we cannot easily redirect back to the original stdout/stderr destinations. * Unsetting working_directory does not restore the original working directory where Unicorn was started. As far as we can tell unsetting this after setting it is rarely desirable and greatly increases the probability of user error. (cherry picked from commit 51b2b90284000aee8d79b37a5406173c45ae212d) --- lib/unicorn/configurator.rb | 16 ++++++--- t/t0012-reload-empty-config.sh | 82 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) create mode 100755 t/t0012-reload-empty-config.sh diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index a927ed8..378a130 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -40,21 +40,24 @@ module Unicorn 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 @@ -361,7 +364,10 @@ module Unicorn # 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 < $tmp +} + +t_begin "replace config file with original(-ish)" && { + grep -v ^pid < $unicorn_config_orig > $unicorn_config + cat >> $unicorn_config </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 -- cgit v1.2.3-24-ge0c7 From 04f0f44f9bd0907fcff1e2cdc59f7e84d4110539 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 23:08:51 +0000 Subject: gemspec: depend on Isolate 3.0.0 for dev No reason to not use the latest and greatest! (cherry picked from commit 570a57c07fd8c3d24b7337637e0dd30136b3a11a) Conflicts: unicorn.gemspec --- unicorn.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unicorn.gemspec b/unicorn.gemspec index 44a6d56..ccf4e09 100644 --- a/unicorn.gemspec +++ b/unicorn.gemspec @@ -49,7 +49,7 @@ Gem::Specification.new do |s| # *strongly* recommended for security reasons. s.add_dependency(%q) - s.add_development_dependency('isolate', '~> 2.0.2') + s.add_development_dependency('isolate', '~> 3.0.0') # s.licenses = %w(GPLv2 Ruby) # licenses= method is not in older RubyGems end -- cgit v1.2.3-24-ge0c7 From 856959cc0b2dbc96f115d26672d0f5b73ae79914 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 23:07:42 +0000 Subject: doc: stop using deprecated rdoc CLI options -N and -a switches no longer exist in rdoc 2.5 (cherry picked from commit 054c7df93db61839648925cfd881ae880709a210) --- GNUmakefile | 2 +- unicorn.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index b5fe9fd..fc56a0f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -189,7 +189,7 @@ atom = $$i; done find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';' - rdoc -a -t "$(shell sed -ne '1s/^= //p' README)" + rdoc -t "$(shell sed -ne '1s/^= //p' README)" install -m644 COPYING doc/COPYING install -m644 $(shell grep '^[A-Z]' .document) doc/ $(MAKE) -C Documentation install-html install-man diff --git a/unicorn.gemspec b/unicorn.gemspec index ccf4e09..973ca09 100644 --- a/unicorn.gemspec +++ b/unicorn.gemspec @@ -36,7 +36,7 @@ Gem::Specification.new do |s| s.homepage = %q{http://unicorn.bogomips.org/} summary = %q{Rack HTTP server for fast clients and Unix} - s.rdoc_options = [ "-Na", "-t", "Unicorn: #{summary}" ] + s.rdoc_options = [ "-t", "Unicorn: #{summary}" ] s.require_paths = %w(lib ext) s.rubyforge_project = %q{mongrel} s.summary = summary -- cgit v1.2.3-24-ge0c7 From ea975cc3e6d2e6ac9c971c8cbda712486ec63c2a Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 27 Oct 2010 23:11:09 +0000 Subject: unicorn 1.0.2 This is the latest maintenance release of the 1.0.x series. All users are encouraged to upgrade to 1.1.x stable series and report bugs there. Shortlog of changes since 1.0.1: Eric Wong (8): SIGTTIN works after SIGWINCH fix delays in signal handling Rakefile: don't post freshmeat on empty changelogs Rakefile: capture prerelease tags configurator: use "__send__" instead of "send" configurator: reloading with unset values restores default gemspec: depend on Isolate 3.0.0 for dev doc: stop using deprecated rdoc CLI options --- GIT-VERSION-GEN | 2 +- GNUmakefile | 2 +- lib/unicorn/const.rb | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 7d0c7ed..dd2cc51 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.0.1.GIT +DEF_VER=v1.0.2.GIT LF=' ' diff --git a/GNUmakefile b/GNUmakefile index fc56a0f..a3b761a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -169,7 +169,7 @@ NEWS: GIT-VERSION-FILE .manifest $(RAKE) -s news_rdoc > $@+ mv $@+ $@ -SINCE = 0.991.0 +SINCE = 1.0.0 ChangeLog: LOG_VERSION = \ $(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \ echo $(GIT_VERSION) || git describe) diff --git a/lib/unicorn/const.rb b/lib/unicorn/const.rb index 51a8a3b..907e9eb 100644 --- a/lib/unicorn/const.rb +++ b/lib/unicorn/const.rb @@ -8,8 +8,8 @@ module Unicorn # Symbols did not really improve things much compared to constants. module Const - # The current version of Unicorn, currently 1.0.1 - UNICORN_VERSION="1.0.1" + # The current version of Unicorn, currently 1.0.2 + UNICORN_VERSION="1.0.2" DEFAULT_HOST = "0.0.0.0" # default TCP listen host address DEFAULT_PORT = 8080 # default TCP listen port -- cgit v1.2.3-24-ge0c7