LP#1042850: Add TCP-level keepalive
authorMike Rylander <mrylander@gmail.com>
Mon, 4 Aug 2014 13:26:56 +0000 (09:26 -0400)
committerMike Rylander <mrylander@gmail.com>
Fri, 5 Dec 2014 17:17:54 +0000 (12:17 -0500)
Some client TCP stacks fail to actually close down their sockets
all the way, leading to a pile up of stale backends that can never
go away.

So, we will use Linux's TCP_KEEPALIVE tuning capabilities to probe
the connection on a regular basis.  This should detect the half-
closed situation and let the backend shut itself down.

Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Bill Erickson <berick@esilibrary.com>
SIPServer.pm

index 4ea82c5..1aba170 100755 (executable)
@@ -26,7 +26,7 @@ use Sys::Syslog qw(syslog);
 use Net::Server::PreFork;
 use Net::Server::Proto;
 use IO::Socket::INET;
-use Socket qw(:crlf);
+use Socket qw(:crlf SOL_SOCKET SO_KEEPALIVE IPPROTO_TCP TCP_KEEPALIVE);
 use Data::Dumper;              # For debugging
 require UNIVERSAL::require;
 
@@ -113,6 +113,19 @@ sub process_request {
     my ($sockaddr, $port, $proto);
     my $transport;
 
+    # This is kind of kinky, but allows us to avoid requiring Socket::Linux.
+    # A simple "Socket::Linux"->use won't suffice since we need access to
+    # all of it's bareword constants as well.
+    eval <<'    EVAL';
+    use Socket::Linux qw(TCP_KEEPINTVL TCP_KEEPIDLE TCP_KEEPCNT);
+    setsockopt($self->{server}->{client}, SOL_SOCKET,  SO_KEEPALIVE, 1);
+    setsockopt($self->{server}->{client}, IPPROTO_TCP, TCP_KEEPIDLE, 120);
+    setsockopt($self->{server}->{client}, IPPROTO_TCP, TCP_KEEPINTVL, 10);
+    EVAL
+
+    syslog('LOG_DEBUG', 
+        "Consider installing Socket::Linux for TCP keepalive: $@") if $@;
+
     $self->{account} = undef; # New connection, no need to keep login info
     $self->{config} = $config;