2
0
mirror of https://git.postgresql.org/git/postgresql.git synced 2025-02-23 19:39:53 +08:00

Support tcp_keepalives_idle option on Solaris.

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  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
This commit is contained in:
Tom Lane 2017-06-27 18:47:57 -04:00
parent 9c7dc89282
commit f0256c774d
2 changed files with 48 additions and 15 deletions
src
backend/libpq
interfaces/libpq

View 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;

View 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,