Skip to content

Commit 9ce7f39

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 66dee28 commit 9ce7f39

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
@@ -1263,7 +1263,8 @@ setKeepalivesIdle(PGconn *conn)
12631263
if (idle < 0)
12641264
idle = 0;
12651265

1266-
#ifdef TCP_KEEPIDLE
1266+
#if defined(TCP_KEEPIDLE)
1267+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
12671268
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
12681269
(char *) &idle, sizeof(idle)) < 0)
12691270
{
@@ -1274,9 +1275,20 @@ setKeepalivesIdle(PGconn *conn)
12741275
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
12751276
return 0;
12761277
}
1277-
#else
1278-
#ifdef TCP_KEEPALIVE
1279-
/* Darwin uses TCP_KEEPALIVE rather than TCP_KEEPIDLE */
1278+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1279+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1280+
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1281+
(char *) &idle, sizeof(idle)) < 0)
1282+
{
1283+
char sebuf[256];
1284+
1285+
appendPQExpBuffer(&conn->errorMessage,
1286+
libpq_gettext("setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %s\n"),
1287+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1288+
return 0;
1289+
}
1290+
#elif defined(TCP_KEEPALIVE)
1291+
/* TCP_KEEPALIVE is the name of this option on macOS */
12801292
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
12811293
(char *) &idle, sizeof(idle)) < 0)
12821294
{
@@ -1287,7 +1299,6 @@ setKeepalivesIdle(PGconn *conn)
12871299
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
12881300
return 0;
12891301
}
1290-
#endif
12911302
#endif
12921303

12931304
return 1;
@@ -1355,7 +1366,7 @@ setKeepalivesCount(PGconn *conn)
13551366

13561367
return 1;
13571368
}
1358-
#else /* Win32 */
1369+
#else /* WIN32 */
13591370
#ifdef SIO_KEEPALIVE_VALS
13601371
/*
13611372
* Enable keepalives and set the keepalive values on Win32,

0 commit comments

Comments
 (0)