From a3ee71cc539022cab46f3d5ca181ad088dc85f2b Mon Sep 17 00:00:00 2001 From: Sagi Shnaidman Date: Mon, 27 Jun 2016 15:28:44 +0300 Subject: [PATCH] Support TCP keepalives in geard Support configuration of TCP keepalives in gear server. When connections are closed not gracefully they stays opened for a long time, which leads to file descriptors leak. Default values for interval, probe and count are such as in most Linux distributions. By default is disabled to keep compatibility with older versions. Change-Id: I335f68a24dda409b1a48c6e4e520ec08dfd38078 --- gear/__init__.py | 16 +++++++++++++++- gear/cmd/geard.py | 19 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/gear/__init__.py b/gear/__init__.py index f775d83..e03f3d0 100644 --- a/gear/__init__.py +++ b/gear/__init__.py @@ -2424,6 +2424,10 @@ class Server(BaseClientServer): access control rules to its connections. :arg str host: Host name or IPv4/IPv6 address to bind to. Defaults to "whatever getaddrinfo() returns", which might be IPv4-only. + :arg bool keepalive: Whether to use TCP keepalives + :arg int tcp_keepidle: Idle time after which to start keepalives sending + :arg int tcp_keepintvl: Interval in seconds between TCP keepalives + :arg int tcp_keepcnt: Count of TCP keepalives to send before disconnect """ edge_bitmask = select.EPOLLET @@ -2433,7 +2437,8 @@ class Server(BaseClientServer): def __init__(self, port=4730, ssl_key=None, ssl_cert=None, ssl_ca=None, statsd_host=None, statsd_port=8125, statsd_prefix=None, - server_id=None, acl=None, host=None): + server_id=None, acl=None, host=None, keepalive=False, + tcp_keepidle=7200, tcp_keepintvl=75, tcp_keepcnt=9): self.port = port self.ssl_key = ssl_key self.ssl_cert = ssl_cert @@ -2462,6 +2467,15 @@ class Server(BaseClientServer): self.socket = socket.socket(af, socktype, proto) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if keepalive: + self.socket.setsockopt(socket.SOL_SOCKET, + socket.SO_KEEPALIVE, 1) + self.socket.setsockopt(socket.IPPROTO_TCP, + socket.TCP_KEEPIDLE, tcp_keepidle) + self.socket.setsockopt(socket.IPPROTO_TCP, + socket.TCP_KEEPINTVL, tcp_keepintvl) + self.socket.setsockopt(socket.IPPROTO_TCP, + socket.TCP_KEEPCNT, tcp_keepcnt) except socket.error: self.socket = None continue diff --git a/gear/cmd/geard.py b/gear/cmd/geard.py index 762d956..d35dc25 100644 --- a/gear/cmd/geard.py +++ b/gear/cmd/geard.py @@ -60,6 +60,18 @@ support. help='path to SSL private key') parser.add_argument('--acl', dest='acl', metavar='PATH', help='path to ACL file') + parser.add_argument('--keepalive', dest='keepalive', default=False, + action='store_true', + help='enable TCP keepalives in socket') + parser.add_argument('--keepalive-idle', dest='tcp_keepidle', type=int, + default=7200, action='store', + help='TCP keepalive idle time') + parser.add_argument('--keepalive-interval', dest='tcp_keepintvl', type=int, + default=75, action='store', + help='TCP keepalive probe interval') + parser.add_argument('--keepalive-count', dest='tcp_keepcnt', type=int, + default=9, action='store', + help='TCP keepalive probes count') parser.add_argument('--version', dest='version', action='store_true', help='show version') self.args = parser.parse_args() @@ -109,7 +121,12 @@ support. statsd_host, statsd_port, statsd_prefix, - acl=acl) + acl=acl, + keepalive=self.args.keepalive, + tcp_keepidle=self.args.tcp_keepidle, + tcp_keepintvl=self.args.tcp_keepintvl, + tcp_keepcnt=self.args.tcp_keepcnt + ) signal.pause()