summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2013-02-08 16:30:21 +0100
committerantirez <antirez@gmail.com>2013-02-11 11:47:20 +0100
commit609a3ec1be7cf49411129805a5bf2ca660c9dd02 (patch)
treee4c074cd199b858b5dc77db39c474ecdd273232d
parent0b50d1ce9aa27b049dde5191a1a1ff1cdde3eca4 (diff)
downloadredis-609a3ec1be7cf49411129805a5bf2ca660c9dd02.tar.gz
Add SO_KEEPALIVE support to anet.c.
-rw-r--r--src/anet.c43
-rw-r--r--src/anet.h1
2 files changed, 44 insertions, 0 deletions
diff --git a/src/anet.c b/src/anet.c
index 3f037dcad..82bca5534 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -75,6 +75,49 @@ int anetNonBlock(char *err, int fd)
return ANET_OK;
}
+/* Set TCP keep alive option to detect dead peers. The interval option
+ * is only used for Linux as we are using Linux-specific APIs to set
+ * the probe send time, interval, and count. */
+int anetKeepAlive(char *err, int fd, int interval)
+{
+ int val = 1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)
+ {
+ anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno));
+ return ANET_ERR;
+ }
+
+#ifdef __linux__
+ /* Default settings are more or less garbage, with the keepalive time
+ * set to 7200 by default on Linux. Modify settings to make the feature
+ * actually useful. */
+
+ /* Send first probe after interval. */
+ val = interval;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
+ anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno));
+ return ANET_ERR;
+ }
+
+ /* Send next probes after interval. */
+ val = interval;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
+ anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno));
+ return ANET_ERR;
+ }
+
+ /* Consider the socket in error state after just one missing ACK reply. */
+ val = 1;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
+ anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno));
+ return ANET_ERR;
+ }
+#endif
+
+ return ANET_OK;
+}
+
static int anetSetTcpNoDelay(char *err, int fd, int val)
{
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1)
diff --git a/src/anet.h b/src/anet.h
index dbf36dbd8..696c2c225 100644
--- a/src/anet.h
+++ b/src/anet.h
@@ -55,5 +55,6 @@ int anetEnableTcpNoDelay(char *err, int fd);
int anetDisableTcpNoDelay(char *err, int fd);
int anetTcpKeepAlive(char *err, int fd);
int anetPeerToString(int fd, char *ip, int *port);
+int anetKeepAlive(char *err, int fd, int interval);
#endif