]> git.ipfire.org Git - thirdparty/postgresql.git/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 3296b756bb70d2401cfb399ddc07a21af19fea4c..17406d1e722a0bf95963f4e1ee2f66056734938f 100644 (file)
@@ -1570,7 +1570,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;
 
@@ -1582,7 +1582,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)
@@ -1590,7 +1591,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)
@@ -1598,7 +1609,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;
@@ -1617,7 +1628,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;
 
@@ -1636,14 +1648,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)
        {
@@ -1656,7 +1678,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");
@@ -1706,7 +1728,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 25a33eccd4df28230f75a1e2e8c7d2e004916427..4a71ddcf422d9f4a2041d789f6fc3b15dde092de 100644 (file)
@@ -1192,7 +1192,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)
        {
@@ -1203,9 +1204,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)
        {
@@ -1216,7 +1228,6 @@ setKeepalivesIdle(PGconn *conn)
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return 0;
        }
-#endif
 #endif
 
        return 1;
@@ -1284,7 +1295,7 @@ setKeepalivesCount(PGconn *conn)
 
        return 1;
 }
-#else                                                  /* Win32 */
+#else                                                  /* WIN32 */
 #ifdef SIO_KEEPALIVE_VALS
 /*
  * Enable keepalives and set the keepalive values on Win32,