]> 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 ba42753c067e4f12a0e111ca657bb2fb9780357b..65b02060383e5124c2192bca524b79e64c686d23 100644 (file)
@@ -1653,7 +1653,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;
 
@@ -1665,7 +1665,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)
@@ -1673,7 +1674,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)
@@ -1681,7 +1692,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;
@@ -1700,7 +1711,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;
 
@@ -1719,14 +1731,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)
        {
@@ -1739,7 +1761,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");
@@ -1789,7 +1811,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 ec468870d2a5194f1abee36dcccd22e6ff986318..443b4fb3e2be42eb540508afa0376b5103e41ca8 100644 (file)
@@ -1280,7 +1280,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)
        {
@@ -1291,9 +1292,20 @@ setKeepalivesIdle(PGconn *conn)
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return 0;
        }
-#else
-#ifdef TCP_KEEPALIVE
-       /* Darwin 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)
        {
@@ -1304,7 +1316,6 @@ setKeepalivesIdle(PGconn *conn)
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return 0;
        }
-#endif
 #endif
 
        return 1;
@@ -1372,7 +1383,7 @@ setKeepalivesCount(PGconn *conn)
 
        return 1;
 }
-#else                                                  /* Win32 */
+#else                                                  /* WIN32 */
 #ifdef SIO_KEEPALIVE_VALS
 /*
  * Enable keepalives and set the keepalive values on Win32,