Skip to content

Commit f0256c7

Browse files
committed
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 #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 5acd417, so back-patch to all supported branches. Discussion: https://postgr.es/m/20170627163757.25161.528@wrigleys.postgresql.org
1 parent 9c7dc89 commit f0256c7

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

src/backend/libpq/pqcomm.c

+31-9
Original file line numberDiff line numberDiff line change
@@ -1676,7 +1676,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
16761676
int
16771677
pq_getkeepalivesidle(Port *port)
16781678
{
1679-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(WIN32)
1679+
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
16801680
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
16811681
return 0;
16821682

@@ -1688,23 +1688,34 @@ pq_getkeepalivesidle(Port *port)
16881688
#ifndef WIN32
16891689
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
16901690

1691-
#ifdef TCP_KEEPIDLE
1691+
#if defined(TCP_KEEPIDLE)
1692+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
16921693
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
16931694
(char *) &port->default_keepalives_idle,
16941695
&size) < 0)
16951696
{
16961697
elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
16971698
port->default_keepalives_idle = -1; /* don't know */
16981699
}
1699-
#else
1700+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1701+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1702+
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1703+
(char *) &port->default_keepalives_idle,
1704+
&size) < 0)
1705+
{
1706+
elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1707+
port->default_keepalives_idle = -1; /* don't know */
1708+
}
1709+
#else /* must have TCP_KEEPALIVE */
1710+
/* TCP_KEEPALIVE is the name of this option on macOS */
17001711
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
17011712
(char *) &port->default_keepalives_idle,
17021713
&size) < 0)
17031714
{
17041715
elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
17051716
port->default_keepalives_idle = -1; /* don't know */
17061717
}
1707-
#endif /* TCP_KEEPIDLE */
1718+
#endif /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
17081719
#else /* WIN32 */
17091720
/* We can't get the defaults on Windows, so return "don't know" */
17101721
port->default_keepalives_idle = -1;
@@ -1723,7 +1734,8 @@ pq_setkeepalivesidle(int idle, Port *port)
17231734
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
17241735
return STATUS_OK;
17251736

1726-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
1737+
/* check SIO_KEEPALIVE_VALS here, not just WIN32, as some toolchains lack it */
1738+
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
17271739
if (idle == port->keepalives_idle)
17281740
return STATUS_OK;
17291741

@@ -1742,14 +1754,24 @@ pq_setkeepalivesidle(int idle, Port *port)
17421754
if (idle == 0)
17431755
idle = port->default_keepalives_idle;
17441756

1745-
#ifdef TCP_KEEPIDLE
1757+
#if defined(TCP_KEEPIDLE)
1758+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
17461759
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
17471760
(char *) &idle, sizeof(idle)) < 0)
17481761
{
17491762
elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
17501763
return STATUS_ERROR;
17511764
}
1752-
#else
1765+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1766+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1767+
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1768+
(char *) &idle, sizeof(idle)) < 0)
1769+
{
1770+
elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1771+
return STATUS_ERROR;
1772+
}
1773+
#else /* must have TCP_KEEPALIVE */
1774+
/* TCP_KEEPALIVE is the name of this option on macOS */
17531775
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
17541776
(char *) &idle, sizeof(idle)) < 0)
17551777
{
@@ -1762,7 +1784,7 @@ pq_setkeepalivesidle(int idle, Port *port)
17621784
#else /* WIN32 */
17631785
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
17641786
#endif
1765-
#else /* TCP_KEEPIDLE || SIO_KEEPALIVE_VALS */
1787+
#else /* no way to set it */
17661788
if (idle != 0)
17671789
{
17681790
elog(LOG, "setting the keepalive idle time is not supported");
@@ -1812,7 +1834,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
18121834
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
18131835
return STATUS_OK;
18141836

1815-
#if defined(TCP_KEEPINTVL) || defined (SIO_KEEPALIVE_VALS)
1837+
#if defined(TCP_KEEPINTVL) || defined(SIO_KEEPALIVE_VALS)
18161838
if (interval == port->keepalives_interval)
18171839
return STATUS_OK;
18181840

src/interfaces/libpq/fe-connect.c

+17-6
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,8 @@ setKeepalivesIdle(PGconn *conn)
14701470
if (idle < 0)
14711471
idle = 0;
14721472

1473-
#ifdef TCP_KEEPIDLE
1473+
#if defined(TCP_KEEPIDLE)
1474+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
14741475
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
14751476
(char *) &idle, sizeof(idle)) < 0)
14761477
{
@@ -1481,9 +1482,20 @@ setKeepalivesIdle(PGconn *conn)
14811482
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
14821483
return 0;
14831484
}
1484-
#else
1485-
#ifdef TCP_KEEPALIVE
1486-
/* macOS uses TCP_KEEPALIVE rather than TCP_KEEPIDLE */
1485+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1486+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1487+
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1488+
(char *) &idle, sizeof(idle)) < 0)
1489+
{
1490+
char sebuf[256];
1491+
1492+
appendPQExpBuffer(&conn->errorMessage,
1493+
libpq_gettext("setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %s\n"),
1494+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1495+
return 0;
1496+
}
1497+
#elif defined(TCP_KEEPALIVE)
1498+
/* TCP_KEEPALIVE is the name of this option on macOS */
14871499
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
14881500
(char *) &idle, sizeof(idle)) < 0)
14891501
{
@@ -1494,7 +1506,6 @@ setKeepalivesIdle(PGconn *conn)
14941506
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
14951507
return 0;
14961508
}
1497-
#endif
14981509
#endif
14991510

15001511
return 1;
@@ -1562,7 +1573,7 @@ setKeepalivesCount(PGconn *conn)
15621573

15631574
return 1;
15641575
}
1565-
#else /* Win32 */
1576+
#else /* WIN32 */
15661577
#ifdef SIO_KEEPALIVE_VALS
15671578
/*
15681579
* Enable keepalives and set the keepalive values on Win32,

0 commit comments

Comments
 (0)