Re: Setting TCP keepalive for Cyrus daemons

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Feb 12, 2010 at 09:45:02AM -0600, Gary Mills wrote:
> I'm willing to add a `keepalive' option to Cyrus master along with the
> setsockopt() system call to enable that setting.  This option could be
> added to the cyrus.conf file for any services that could benefit from
> it. Would this be a reasonable addition to Cyrus?

How does this look?

+{ "tcp_keepalive", 0, SWITCH }
+/* Enable keepalive on TCP connections */
+
+{ "tcp_keepalive_cnt", 0, INT }
+/* Number of TCP keepalive probes to send before declaring the 
+   connection dead (0 == system default) */
+
+{ "tcp_keepalive_idle", 0, INT }
+/* Number of seconds a connection must be idle before keepalive
+   probes are sent (0 == system default) */
+
+{ "tcp_keepalive_intvl", 0, INT }
+/* Number of seconds between keepalive probes (0 == system default) */

A switch to enable keepalive, plus options to edit each of the
tunables.  The full patch is attached - not tested except for
a compile yet.

Bron.
diff --git a/imap/sync_client.c b/imap/sync_client.c
index b26768d..41ac6c1 100644
--- a/imap/sync_client.c
+++ b/imap/sync_client.c
@@ -3418,6 +3418,36 @@ struct backend *replica_connect(struct backend *be, const char *servername,
 			   (void *) &on, sizeof(on)) != 0) {
 		syslog(LOG_ERR, "unable to setsocketopt(TCP_NODELAY): %m");
 	    }
+
+            /* turn on TCP keepalive if set */
+            if (config_getswitch(IMAPOPT_TCP_KEEPALIVE)) {
+		int r;
+                int optval = 1;
+                socklen_t optlen = sizeof(optval);
+
+                r = setsockopt(be->sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
+                if (r < 0) {
+                    syslog(LOG_ERR, "unable to setsocketopt(SO_KEEPALIVE): %m");
+                }
+                if (config_getint(IMAPOPT_TCP_KEEPALIVE_CNT)) {
+                    r = setsockopt(be->sock, SOL_TCP, TCP_KEEPCNT, &optval, optlen);
+                    if (r < 0) {
+                        syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPCNT): %m");
+                    }
+                }
+                if (config_getint(IMAPOPT_TCP_KEEPALIVE_IDLE)) {
+                    r = setsockopt(be->sock, SOL_TCP, TCP_KEEPIDLE, &optval, optlen);
+                    if (r < 0) {
+                        syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPIDLE): %m");
+                    }
+                }
+                if (config_getint(IMAPOPT_TCP_KEEPALIVE_INTVL)) {
+                    r = setsockopt(be->sock, SOL_TCP, TCP_KEEPINTVL, &optval, optlen);
+                    if (r < 0) {
+                        syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPINTVL): %m");
+                    }
+                }
+	    }
 	} else {
 	    syslog(LOG_ERR, "unable to getprotobyname(\"tcp\"): %m");
 	}
diff --git a/lib/imapoptions b/lib/imapoptions
index 1ae2da0..52224e5 100644
--- a/lib/imapoptions
+++ b/lib/imapoptions
@@ -1139,6 +1139,20 @@ product version in the capabilities */
 { "syslog_prefix", NULL, STRING }
 /* String to be prepended to the process name in syslog entries. */
 
+{ "tcp_keepalive", 0, SWITCH }
+/* Enable keepalive on TCP connections */
+
+{ "tcp_keepalive_cnt", 0, INT }
+/* Number of TCP keepalive probes to send before declaring the 
+   connection dead (0 == system default) */
+
+{ "tcp_keepalive_idle", 0, INT }
+/* Number of seconds a connection must be idle before keepalive
+   probes are sent (0 == system default) */
+
+{ "tcp_keepalive_intvl", 0, INT }
+/* Number of seconds between keepalive probes (0 == system default) */
+
 { "temp_path", "/tmp", STRING }
 /* The pathname to store temporary files in */
 
diff --git a/master/service.c b/master/service.c
index ab1409b..395e3ff 100644
--- a/master/service.c
+++ b/master/service.c
@@ -61,6 +61,7 @@
 #include <netdb.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -512,8 +513,41 @@ int main(int argc, char **argv, char **envp)
 		close(fd);
 		continue;
 	    }
+
+	    /* turn on TCP keepalive if set */
+	    if (config_getswitch(IMAPOPT_TCP_KEEPALIVE)) {
+		int r;
+		int optval = 1;
+		socklen_t optlen = sizeof(optval);
+
+		r = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
+		if (r < 0) {
+		    syslog(LOG_ERR, "unable to setsocketopt(SO_KEEPALIVE): %m");
+		}
+		optval = config_getint(IMAPOPT_TCP_KEEPALIVE_CNT);
+		if (optval) {
+		    r = setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &optval, optlen);
+		    if (r < 0) {
+			syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPCNT): %m");
+		    }
+		}
+		optval = config_getint(IMAPOPT_TCP_KEEPALIVE_IDLE);
+		if (optval) {
+		    r = setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen);
+		    if (r < 0) {
+			syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPIDLE): %m");
+		    }
+		}
+		optval = config_getint(IMAPOPT_TCP_KEEPALIVE_INTVL);
+		if (optval) {
+		    r = setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen);
+		    if (r < 0) {
+			syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPINTVL): %m");
+		    }
+		}
+	    }
 	}
-	
+
 	notify_master(STATUS_FD, MASTER_SERVICE_UNAVAILABLE);
 	syslog(LOG_DEBUG, "accepted connection");
 
----
Cyrus Home Page: http://cyrusimap.web.cmu.edu/
Cyrus Wiki/FAQ: http://cyrusimap.web.cmu.edu/twiki
List Archives/Info: http://asg.web.cmu.edu/cyrus/mailing-list.html

[Index of Archives]     [Cyrus SASL]     [Squirrel Mail]     [Asterisk PBX]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [KDE]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux