avoid IO_PURGATORY on Ruby 1.9+
authorEric Wong <e@80x24.org>
Fri, 25 Oct 2013 19:45:15 +0000 (25 19:45 +0000)
committerEric Wong <normalperson@yhbt.net>
Fri, 25 Oct 2013 20:00:41 +0000 (25 20:00 +0000)
Ruby 1.9 and later includes IO#autoclose=, so we can use it
and prevent some dead IO objects from hanging around.

lib/unicorn/http_server.rb
lib/unicorn/socket_helper.rb

index cd160c5..a6266ea 100644 (file)
@@ -254,7 +254,7 @@ class Unicorn::HttpServer
     begin
       io = bind_listen(address, opt)
       unless Kgio::TCPServer === io || Kgio::UNIXServer === io
-        IO_PURGATORY << io
+        prevent_autoclose(io)
         io = server_cast(io)
       end
       logger.info "listening on addr=#{sock_name(io)} fd=#{io.fileno}"
@@ -466,7 +466,7 @@ class Unicorn::HttpServer
       (3..1024).each do |io|
         next if listener_fds.include?(io)
         io = IO.for_fd(io) rescue next
-        IO_PURGATORY << io
+        prevent_autoclose(io)
         io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
       end
 
@@ -772,7 +772,7 @@ class Unicorn::HttpServer
     inherited = ENV['UNICORN_FD'].to_s.split(/,/).map do |fd|
       io = Socket.for_fd(fd.to_i)
       set_server_sockopt(io, listener_opts[sock_name(io)])
-      IO_PURGATORY << io
+      prevent_autoclose(io)
       logger.info "inherited addr=#{sock_name(io)} fd=#{fd}"
       server_cast(io)
     end
index 2701d58..820b778 100644 (file)
@@ -8,6 +8,7 @@ module Unicorn
     include Socket::Constants
 
     # prevents IO objects in here from being GC-ed
+    # kill this when we drop 1.8 support
     IO_PURGATORY = []
 
     # internal interface, only used by Rainbows!/Zbatery
@@ -59,6 +60,14 @@ module Unicorn
       end if defined?(SO_ACCEPTFILTER)
     end
 
+    def prevent_autoclose(io)
+      if io.respond_to?(:autoclose=)
+        io.autoclose = false
+      else
+        IO_PURGATORY << io
+      end
+    end
+
     def set_tcp_sockopt(sock, opt)
       # just in case, even LANs can break sometimes.  Linux sysadmins
       # can lower net.ipv4.tcp_keepalive_* sysctl knobs to very low values.
@@ -174,7 +183,7 @@ module Unicorn
         sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
       end
       sock.bind(Socket.pack_sockaddr_in(port, addr))
-      IO_PURGATORY << sock
+      prevent_autoclose(sock)
       Kgio::TCPServer.for_fd(sock.fileno)
     end