]> granicus.if.org Git - postgresql/commitdiff
Support tcp_keepalives_idle option on Solaris.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 27 Jun 2017 22:47:57 +0000 (18:47 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 27 Jun 2017 22:47:57 +0000 (18:47 -0400)
Turns out that the socket option for this is named TCP_KEEPALIVE_THRESHOLD,
at least according to the tcp(7P) man page for Solaris 11.  (But since that
text refers to "SunOS", it's likely pretty ancient.)  It appears that the
symbol TCP_KEEPALIVE does get defined on that platform, but it doesn't
seem to represent a valid protocol-level socket option.  This leads to
bleats in the postmaster log, and no tcp_keepalives_idle functionality.

Per bug #14720 from Andrey Lizenko, as well as an earlier report from
Dhiraj Chawla that nobody had followed up on.  The issue's been there
since we added the TCP_KEEPALIVE code path in commit 5acd417c8, so
back-patch to all supported branches.

Discussion: https://postgr.es/m/20170627163757.25161.528@wrigleys.postgresql.org

src/backend/libpq/pqcomm.c
src/interfaces/libpq/fe-connect.c

index 261e9be8281dda96cab73400388b09cc484b1e0c..c62f7e9ab330845d6c0bffed100f641d61bc4a7d 100644 (file)
@@ -1676,7 +1676,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
 int
 pq_getkeepalivesidle(Port *port)
 {
-#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(WIN32)
+#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
        if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
                return 0;
 
@@ -1688,7 +1688,8 @@ pq_getkeepalivesidle(Port *port)
 #ifndef WIN32
                ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
 
-#ifdef TCP_KEEPIDLE
+#if defined(TCP_KEEPIDLE)
+               /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
                if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
                                           (char *) &port->default_keepalives_idle,
                                           &size) < 0)
@@ -1696,7 +1697,17 @@ pq_getkeepalivesidle(Port *port)
                        elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
                        port->default_keepalives_idle = -1; /* don't know */
                }
-#else
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+               /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
+               if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
+                                          (char *) &port->default_keepalives_idle,
+                                          &size) < 0)
+               {
+                       elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
+                       port->default_keepalives_idle = -1; /* don't know */
+               }
+#else                                                  /* must have TCP_KEEPALIVE */
+               /* TCP_KEEPALIVE is the name of this option on macOS */
                if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
                                           (char *) &port->default_keepalives_idle,
                                           &size) < 0)
@@ -1704,7 +1715,7 @@ pq_getkeepalivesidle(Port *port)
                        elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
                        port->default_keepalives_idle = -1; /* don't know */
                }
-#endif                                                 /* TCP_KEEPIDLE */
+#endif                                                 /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
 #else                                                  /* WIN32 */
                /* We can't get the defaults on Windows, so return "don't know" */
                port->default_keepalives_idle = -1;
@@ -1723,7 +1734,8 @@ pq_setkeepalivesidle(int idle, Port *port)
        if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
                return STATUS_OK;
 
-#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
+/* check SIO_KEEPALIVE_VALS here, not just WIN32, as some toolchains lack it */
+#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
        if (idle == port->keepalives_idle)
                return STATUS_OK;
 
@@ -1742,14 +1754,24 @@ pq_setkeepalivesidle(int idle, Port *port)
        if (idle == 0)
                idle = port->default_keepalives_idle;
 
-#ifdef TCP_KEEPIDLE
+#if defined(TCP_KEEPIDLE)
+       /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
        if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
                                   (char *) &idle, sizeof(idle)) < 0)
        {
                elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
                return STATUS_ERROR;
        }
-#else
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+       /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
+       if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
+                                  (char *) &idle, sizeof(idle)) < 0)
+       {
+               elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
+               return STATUS_ERROR;
+       }
+#else                                                  /* must have TCP_KEEPALIVE */
+       /* TCP_KEEPALIVE is the name of this option on macOS */
        if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
                                   (char *) &idle, sizeof(idle)) < 0)
        {
@@ -1762,7 +1784,7 @@ pq_setkeepalivesidle(int idle, Port *port)
 #else                                                  /* WIN32 */
        return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
 #endif
-#else                                                  /* TCP_KEEPIDLE || SIO_KEEPALIVE_VALS */
+#else                                                  /* no way to set it */
        if (idle != 0)
        {
                elog(LOG, "setting the keepalive idle time is not supported");
@@ -1812,7 +1834,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
        if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
                return STATUS_OK;
 
-#if defined(TCP_KEEPINTVL) || defined (SIO_KEEPALIVE_VALS)
+#if defined(TCP_KEEPINTVL) || defined(SIO_KEEPALIVE_VALS)
        if (interval == port->keepalives_interval)
                return STATUS_OK;
 
index 764e9601fe9b8185f5c347a531d71aa18f2e54e7..e32c42b4b6b0401dcef6e4c3a9d4c41b81bbff2f 100644 (file)
@@ -1470,7 +1470,8 @@ setKeepalivesIdle(PGconn *conn)
        if (idle < 0)
                idle = 0;
 
-#ifdef TCP_KEEPIDLE
+#if defined(TCP_KEEPIDLE)
+       /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
        if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
                                   (char *) &idle, sizeof(idle)) < 0)
        {
@@ -1481,9 +1482,20 @@ setKeepalivesIdle(PGconn *conn)
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return 0;
        }
-#else
-#ifdef TCP_KEEPALIVE
-       /* macOS uses TCP_KEEPALIVE rather than TCP_KEEPIDLE */
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+       /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
+       if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
+                                  (char *) &idle, sizeof(idle)) < 0)
+       {
+               char            sebuf[256];
+
+               appendPQExpBuffer(&conn->errorMessage,
+                                                 libpq_gettext("setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %s\n"),
+                                                 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+               return 0;
+       }
+#elif defined(TCP_KEEPALIVE)
+       /* TCP_KEEPALIVE is the name of this option on macOS */
        if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
                                   (char *) &idle, sizeof(idle)) < 0)
        {
@@ -1494,7 +1506,6 @@ setKeepalivesIdle(PGconn *conn)
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return 0;
        }
-#endif
 #endif
 
        return 1;
@@ -1562,7 +1573,7 @@ setKeepalivesCount(PGconn *conn)
 
        return 1;
 }
-#else                                                  /* Win32 */
+#else                                                  /* WIN32 */
 #ifdef SIO_KEEPALIVE_VALS
 /*
  * Enable keepalives and set the keepalive values on Win32,