about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/unicorn.rb17
-rw-r--r--test/exec/test_exec.rb32
2 files changed, 45 insertions, 4 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index 02419e7..2883bc2 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -105,16 +105,25 @@ module Unicorn
     # replaces current listener set with +listeners+.  This will
     # close the socket if it will not exist in the new listener set
     def listeners=(listeners)
-      cur_names = listener_names
+      cur_names, dead_names = [], []
+      listener_names.each do |name|
+        if "/" == name[0..0]
+          # mark unlinked sockets as dead so we can rebind them
+          (File.socket?(name) ? cur_names : dead_names) << name
+        else
+          cur_names << name
+        end
+      end
       set_names = listener_names(listeners)
-      dead_names = cur_names - set_names
+      dead_names += cur_names - set_names
+      dead_names.uniq!
 
       @listeners.delete_if do |io|
         if dead_names.include?(sock_name(io))
           @io_purgatory.delete_if do |pio|
-            pio.fileno == io.fileno && (pio.close rescue nil).nil?
+            pio.fileno == io.fileno && (pio.close rescue nil).nil? # true
           end
-          (io.close rescue nil).nil?
+          (io.close rescue nil).nil? # true
         else
           false
         end
diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb
index 336dc53..ec00fac 100644
--- a/test/exec/test_exec.rb
+++ b/test/exec/test_exec.rb
@@ -439,6 +439,38 @@ end
     reexec_basic_test(pid, pid_file)
   end
 
+  def test_socket_unlinked_restore
+    results = nil
+    sock = Tempfile.new('unicorn_test_sock')
+    sock_path = sock.path
+    sock.close!
+    ucfg = Tempfile.new('unicorn_test_config')
+    ucfg.syswrite("listen \"#{sock_path}\"\n")
+
+    File.open("config.ru", "wb") { |fp| fp.syswrite(HI) }
+    pid = xfork { redirect_test_io { exec($unicorn_bin, "-c#{ucfg.path}") } }
+    wait_for_file(sock_path)
+    assert File.socket?(sock_path)
+    assert_nothing_raised do
+      sock = UNIXSocket.new(sock_path)
+      sock.syswrite("GET / HTTP/1.0\r\n\r\n")
+      results = sock.sysread(4096)
+    end
+    assert_equal String, results.class
+    assert_nothing_raised do
+      File.unlink(sock_path)
+      Process.kill(:HUP, pid)
+    end
+    wait_for_file(sock_path)
+    assert File.socket?(sock_path)
+    assert_nothing_raised do
+      sock = UNIXSocket.new(sock_path)
+      sock.syswrite("GET / HTTP/1.0\r\n\r\n")
+      results = sock.sysread(4096)
+    end
+    assert_equal String, results.class
+  end
+
   def test_unicorn_config_file
     pid_file = "#{@tmpdir}/test.pid"
     sock = Tempfile.new('unicorn_test_sock')