Skip to content

Commit c2cb606

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 dc777f9 commit c2cb606

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

src/backend/libpq/pqcomm.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
15931593
int
15941594
pq_getkeepalivesidle(Port *port)
15951595
{
1596-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(WIN32)
1596+
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
15971597
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
15981598
return 0;
15991599

@@ -1605,23 +1605,34 @@ pq_getkeepalivesidle(Port *port)
16051605
#ifndef WIN32
16061606
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
16071607

1608-
#ifdef TCP_KEEPIDLE
1608+
#if defined(TCP_KEEPIDLE)
1609+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
16091610
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
16101611
(char *) &port->default_keepalives_idle,
16111612
&size) < 0)
16121613
{
16131614
elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
16141615
port->default_keepalives_idle = -1; /* don't know */
16151616
}
1616-
#else
1617+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1618+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1619+
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1620+
(char *) &port->default_keepalives_idle,
1621+
&size) < 0)
1622+
{
1623+
elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1624+
port->default_keepalives_idle = -1; /* don't know */
1625+
}
1626+
#else /* must have TCP_KEEPALIVE */
1627+
/* TCP_KEEPALIVE is the name of this option on macOS */
16171628
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
16181629
(char *) &port->default_keepalives_idle,
16191630
&size) < 0)
16201631
{
16211632
elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
16221633
port->default_keepalives_idle = -1; /* don't know */
16231634
}
1624-
#endif /* TCP_KEEPIDLE */
1635+
#endif /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
16251636
#else /* WIN32 */
16261637
/* We can't get the defaults on Windows, so return "don't know" */
16271638
port->default_keepalives_idle = -1;
@@ -1640,7 +1651,8 @@ pq_setkeepalivesidle(int idle, Port *port)
16401651
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
16411652
return STATUS_OK;
16421653

1643-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
1654+
/* check SIO_KEEPALIVE_VALS here, not just WIN32, as some toolchains lack it */
1655+
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
16441656
if (idle == port->keepalives_idle)
16451657
return STATUS_OK;
16461658

@@ -1659,14 +1671,24 @@ pq_setkeepalivesidle(int idle, Port *port)
16591671
if (idle == 0)
16601672
idle = port->default_keepalives_idle;
16611673

1662-
#ifdef TCP_KEEPIDLE
1674+
#if defined(TCP_KEEPIDLE)
1675+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
16631676
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
16641677
(char *) &idle, sizeof(idle)) < 0)
16651678
{
16661679
elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
16671680
return STATUS_ERROR;
16681681
}
1669-
#else
1682+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1683+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1684+
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1685+
(char *) &idle, sizeof(idle)) < 0)
1686+
{
1687+
elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1688+
return STATUS_ERROR;
1689+
}
1690+
#else /* must have TCP_KEEPALIVE */
1691+
/* TCP_KEEPALIVE is the name of this option on macOS */
16701692
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
16711693
(char *) &idle, sizeof(idle)) < 0)
16721694
{
@@ -1679,7 +1701,7 @@ pq_setkeepalivesidle(int idle, Port *port)
16791701
#else /* WIN32 */
16801702
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
16811703
#endif
1682-
#else /* TCP_KEEPIDLE || SIO_KEEPALIVE_VALS */
1704+
#else /* no way to set it */
16831705
if (idle != 0)
16841706
{
16851707
elog(LOG, "setting the keepalive idle time is not supported");
@@ -1729,7 +1751,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
17291751
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
17301752
return STATUS_OK;
17311753

1732-
#if defined(TCP_KEEPINTVL) || defined (SIO_KEEPALIVE_VALS)
1754+
#if defined(TCP_KEEPINTVL) || defined(SIO_KEEPALIVE_VALS)
17331755
if (interval == port->keepalives_interval)
17341756
return STATUS_OK;
17351757

src/interfaces/libpq/fe-connect.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,8 @@ setKeepalivesIdle(PGconn *conn)
12801280
if (idle < 0)
12811281
idle = 0;
12821282

1283-
#ifdef TCP_KEEPIDLE
1283+
#if defined(TCP_KEEPIDLE)
1284+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
12841285
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
12851286
(char *) &idle, sizeof(idle)) < 0)
12861287
{
@@ -1291,9 +1292,20 @@ setKeepalivesIdle(PGconn *conn)
12911292
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
12921293
return 0;
12931294
}
1294-
#else
1295-
#ifdef TCP_KEEPALIVE
1296-
/* Darwin uses TCP_KEEPALIVE rather than TCP_KEEPIDLE */
1295+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1296+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1297+
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1298+
(char *) &idle, sizeof(idle)) < 0)
1299+
{
1300+
char sebuf[256];
1301+
1302+
appendPQExpBuffer(&conn->errorMessage,
1303+
libpq_gettext("setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %s\n"),
1304+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1305+
return 0;
1306+
}
1307+
#elif defined(TCP_KEEPALIVE)
1308+
/* TCP_KEEPALIVE is the name of this option on macOS */
12971309
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
12981310
(char *) &idle, sizeof(idle)) < 0)
12991311
{
@@ -1304,7 +1316,6 @@ setKeepalivesIdle(PGconn *conn)
13041316
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
13051317
return 0;
13061318
}
1307-
#endif
13081319
#endif
13091320

13101321
return 1;
@@ -1372,7 +1383,7 @@ setKeepalivesCount(PGconn *conn)
13721383

13731384
return 1;
13741385
}
1375-
#else /* Win32 */
1386+
#else /* WIN32 */
13761387
#ifdef SIO_KEEPALIVE_VALS
13771388
/*
13781389
* Enable keepalives and set the keepalive values on Win32,

0 commit comments

Comments
 (0)