skytools.set_tcp_keepalive: add compat with newer OSX
authorMarko Kreen <markokr@gmail.com>
Tue, 5 Nov 2013 23:28:31 +0000 (01:28 +0200)
committerMarko Kreen <markokr@gmail.com>
Tue, 5 Nov 2013 23:28:31 +0000 (01:28 +0200)
Newer OSX has Linux-style TCP_KEEPIDLE/TCP_KEEPCNT
socket options, but TCP_KEEPIDLE is missing, instead
it has old well-hidden TCP_KEEPALIVE option.  So it
branches into Linux section and fails there.

This patch detects every Linux option separately
and uses TCP_KEEPALIVE instead TCP_KEEPIDLE
on Darwin.

It does expect that Python is compiled against current
OSX versions, and headers match running kernel.  So if
option is defined in 'socket' module, it works.

Reported-by: Rob Fowler
python/skytools/sockutil.py

index dbcd021b28638c2d0530b6978ba1471bb5b8c72f..c2b42225d6c690d0c2ee2d250582418280de333f 100644 (file)
@@ -51,16 +51,21 @@ def set_tcp_keepalive(fd, keepalive = True,
 
     # turn on keepalive on the connection
     if keepalive:
+        DARWIN_TCP_KEEPALIVE = 0x10
+
         s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
         if hasattr(socket, 'TCP_KEEPCNT'):
-            s.setsockopt(socket.IPPROTO_TCP, getattr(socket, 'TCP_KEEPIDLE'), tcp_keepidle)
             s.setsockopt(socket.IPPROTO_TCP, getattr(socket, 'TCP_KEEPCNT'), tcp_keepcnt)
-            s.setsockopt(socket.IPPROTO_TCP, getattr(socket, 'TCP_KEEPINTVL'), tcp_keepintvl)
+            if hasattr(socket, 'TCP_KEEPINTVL'):
+                s.setsockopt(socket.IPPROTO_TCP, getattr(socket, 'TCP_KEEPINTVL'), tcp_keepintvl)
+            if hasattr(socket, 'TCP_KEEPIDLE'):
+                s.setsockopt(socket.IPPROTO_TCP, getattr(socket, 'TCP_KEEPIDLE'), tcp_keepidle)
+            elif sys.platform == 'darwin':
+                s.setsockopt(socket.IPPROTO_TCP, DARWIN_TCP_KEEPALIVE, tcp_keepidle)
         elif hasattr(socket, 'TCP_KEEPALIVE'):
             s.setsockopt(socket.IPPROTO_TCP, getattr(socket, 'TCP_KEEPALIVE'), tcp_keepidle)
         elif sys.platform == 'darwin':
-            TCP_KEEPALIVE = 0x10
-            s.setsockopt(socket.IPPROTO_TCP, TCP_KEEPALIVE, tcp_keepidle)
+            s.setsockopt(socket.IPPROTO_TCP, DARWIN_TCP_KEEPALIVE, tcp_keepidle)
         elif sys.platform == 'win32':
             #s.ioctl(SIO_KEEPALIVE_VALS, (1, tcp_keepidle*1000, tcp_keepintvl*1000))
             pass