about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-04-10 00:32:40 -0700
committerEric Wong <normalperson@yhbt.net>2009-04-10 10:10:56 -0700
commit0e59330750559e2cb8f81d9568c2100bd5c6aaec (patch)
tree7224505a2a0b37f932386d894ed5e046eda9e4cf
parente83756512c44294137ee3362cf131eed70663fb1 (diff)
downloadunicorn-0e59330750559e2cb8f81d9568c2100bd5c6aaec.tar.gz
Rather than blindly appending to our listener set
with every "listen" directive read in the config
file, reset our internal array.

Listeners specified on the command-line are always
preserved between config reloads.
-rw-r--r--lib/unicorn.rb2
-rw-r--r--test/exec/test_exec.rb35
2 files changed, 36 insertions, 1 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index 6b50319..02419e7 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -59,6 +59,7 @@ module Unicorn
       @io_purgatory = [] # prevents IO objects in here from being GC-ed
       @request = @rd_sig = @wr_sig = nil
       @reexec_pid = 0
+      @init_listeners = options[:listeners] ? options[:listeners].dup : []
       @config = Configurator.new(options.merge(:use_defaults => true))
       @listener_opts = {}
       @config.commit!(self, :skip => [:listeners, :pid])
@@ -570,6 +571,7 @@ module Unicorn
     def load_config!
       begin
         logger.info "reloading config_file=#{@config.config_file}"
+        @config[:listeners].replace(@init_listeners)
         @config.reload
         @config.commit!(self)
         kill_each_worker(:QUIT)
diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb
index 6c3d282..336dc53 100644
--- a/test/exec/test_exec.rb
+++ b/test/exec/test_exec.rb
@@ -231,6 +231,38 @@ end
     end
   end
 
+  def test_unicorn_config_listener_swap
+    port_cli = unused_port
+    File.open("config.ru", "wb") { |fp| fp.syswrite(HI) }
+    ucfg = Tempfile.new('unicorn_test_config')
+    ucfg.syswrite("listen '#@addr:#@port'\n")
+    pid = xfork do
+      redirect_test_io do
+        exec($unicorn_bin, "-c#{ucfg.path}", "-l#@addr:#{port_cli}")
+      end
+    end
+    results = retry_hit(["http://#@addr:#{port_cli}/"])
+    assert_equal String, results[0].class
+    results = retry_hit(["http://#@addr:#@port/"])
+    assert_equal String, results[0].class
+
+    port2 = unused_port(@addr)
+    ucfg.sysseek(0)
+    ucfg.truncate(0)
+    ucfg.syswrite("listen '#@addr:#{port2}'\n")
+    Process.kill(:HUP, pid)
+
+    results = retry_hit(["http://#@addr:#{port2}/"])
+    assert_equal String, results[0].class
+    results = retry_hit(["http://#@addr:#{port_cli}/"])
+    assert_equal String, results[0].class
+    assert_nothing_raised do
+      reuse = TCPServer.new(@addr, @port)
+      reuse.close
+    end
+    assert_shutdown(pid)
+  end
+
   def test_unicorn_config_listen_with_options
     File.open("config.ru", "wb") { |fp| fp.syswrite(HI) }
     ucfg = Tempfile.new('unicorn_test_config')
@@ -442,7 +474,7 @@ end
     assert_equal String, results.class
 
     # try reloading the config
-    sock = Tempfile.new('unicorn_test_sock')
+    sock = Tempfile.new('new_test_sock')
     new_sock_path = sock.path
     @sockets << new_sock_path
     sock.close!
@@ -452,6 +484,7 @@ end
 
     assert_nothing_raised do
       ucfg = File.open(ucfg.path, "wb")
+      ucfg.syswrite("listen \"#{sock_path}\"\n")
       ucfg.syswrite("listen \"#{new_sock_path}\"\n")
       ucfg.syswrite("pid \"#{pid_file}\"\n")
       ucfg.syswrite("logger Logger.new('#{new_log.path}')\n")