about summary refs log tree commit homepage
path: root/lib/unicorn/socket_helper.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unicorn/socket_helper.rb')
-rw-r--r--lib/unicorn/socket_helper.rb23
1 files changed, 19 insertions, 4 deletions
diff --git a/lib/unicorn/socket_helper.rb b/lib/unicorn/socket_helper.rb
index df8315e..f52dde2 100644
--- a/lib/unicorn/socket_helper.rb
+++ b/lib/unicorn/socket_helper.rb
@@ -3,6 +3,18 @@
 require 'socket'
 
 module Unicorn
+
+  # Instead of using a generic Kgio::Socket for everything,
+  # tag TCP sockets so we can use TCP_INFO under Linux without
+  # incurring extra syscalls for Unix domain sockets.
+  # TODO: remove these when we remove kgio
+  TCPClient = Class.new(Kgio::Socket) # :nodoc:
+  class TCPSrv < Kgio::TCPServer # :nodoc:
+    def kgio_tryaccept # :nodoc:
+      super(TCPClient)
+    end
+  end
+
   module SocketHelper
 
     # internal interface
@@ -63,12 +75,15 @@ module Unicorn
       elsif respond_to?(:accf_arg)
         name = opt[:accept_filter]
         name = DEFAULTS[:accept_filter] if name.nil?
+        sock.listen(opt[:backlog])
+        got = (sock.getsockopt(:SOL_SOCKET, :SO_ACCEPTFILTER) rescue nil).to_s
+        arg = accf_arg(name)
         begin
-          sock.setsockopt(:SOL_SOCKET, :SO_ACCEPTFILTER, accf_arg(name))
+          sock.setsockopt(:SOL_SOCKET, :SO_ACCEPTFILTER, arg)
         rescue => e
           logger.error("#{sock_name(sock)} " \
                        "failed to set accept_filter=#{name} (#{e.inspect})")
-        end
+        end if arg != got
       end
     end
 
@@ -148,7 +163,7 @@ module Unicorn
       end
       sock.bind(Socket.pack_sockaddr_in(port, addr))
       sock.autoclose = false
-      Kgio::TCPServer.for_fd(sock.fileno)
+      TCPSrv.for_fd(sock.fileno)
     end
 
     # returns rfc2732-style (e.g. "[::1]:666") addresses for IPv6
@@ -185,7 +200,7 @@ module Unicorn
     def server_cast(sock)
       begin
         Socket.unpack_sockaddr_in(sock.getsockname)
-        Kgio::TCPServer.for_fd(sock.fileno)
+        TCPSrv.for_fd(sock.fileno)
       rescue ArgumentError
         Kgio::UNIXServer.for_fd(sock.fileno)
       end