Skip to content

Commit 99255d7

Browse files
committed
Second try at fixing tcp_keepalives_idle option on Solaris.
Buildfarm evidence shows that TCP_KEEPALIVE_THRESHOLD doesn't exist after all on Solaris < 11. This means we need to take positive action to prevent the TCP_KEEPALIVE code path from being taken on that platform. I've chosen to limit it with "&& defined(__darwin__)", since it's unclear that anyone else would follow Apple's precedent of spelling the symbol that way. Also, follow a suggestion from Michael Paquier of eliminating code duplication by defining a couple of intermediate symbols for the socket option. In passing, make some effort to reduce the number of translatable messages by replacing "setsockopt(foo) failed" with "setsockopt(%s) failed", etc, throughout the affected files. And update relevant documentation so that it doesn't claim to provide an exhaustive list of the possible socket option names. Like the previous commit (f0256c7), back-patch to all supported branches. Discussion: https://postgr.es/m/20170627163757.25161.528@wrigleys.postgresql.org
1 parent 4500edc commit 99255d7

File tree

4 files changed

+86
-106
lines changed

4 files changed

+86
-106
lines changed

doc/src/sgml/config.sgml

+10-9
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,8 @@ include_dir 'conf.d'
856856
Specifies the number of seconds of inactivity after which TCP
857857
should send a keepalive message to the client. A value of 0 uses
858858
the system default.
859-
This parameter is supported only on systems that support the
860-
<symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</> symbols, and on
859+
This parameter is supported only on systems that support
860+
<symbol>TCP_KEEPIDLE</> or an equivalent socket option, and on
861861
Windows; on other systems, it must be zero.
862862
In sessions connected via a Unix-domain socket, this parameter is
863863
ignored and always reads as zero.
@@ -882,9 +882,9 @@ include_dir 'conf.d'
882882
Specifies the number of seconds after which a TCP keepalive message
883883
that is not acknowledged by the client should be retransmitted.
884884
A value of 0 uses the system default.
885-
This parameter is supported only on systems that support the
886-
<symbol>TCP_KEEPINTVL</> symbol, and on Windows; on other systems, it
887-
must be zero.
885+
This parameter is supported only on systems that support
886+
<symbol>TCP_KEEPINTVL</> or an equivalent socket option, and on
887+
Windows; on other systems, it must be zero.
888888
In sessions connected via a Unix-domain socket, this parameter is
889889
ignored and always reads as zero.
890890
</para>
@@ -906,10 +906,11 @@ include_dir 'conf.d'
906906
<listitem>
907907
<para>
908908
Specifies the number of TCP keepalives that can be lost before
909-
the server's connection to the client is considered dead. A value of 0
910-
uses the system default. This parameter is
911-
supported only on systems that support the <symbol>TCP_KEEPCNT</>
912-
symbol; on other systems, it must be zero.
909+
the server's connection to the client is considered dead.
910+
A value of 0 uses the system default.
911+
This parameter is supported only on systems that support
912+
<symbol>TCP_KEEPCNT</> or an equivalent socket option;
913+
on other systems, it must be zero.
913914
In sessions connected via a Unix-domain socket, this parameter is
914915
ignored and always reads as zero.
915916
</para>

doc/src/sgml/libpq.sgml

+10-9
Original file line numberDiff line numberDiff line change
@@ -1125,10 +1125,10 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
11251125
Controls the number of seconds of inactivity after which TCP should
11261126
send a keepalive message to the server. A value of zero uses the
11271127
system default. This parameter is ignored for connections made via a
1128-
Unix-domain socket, or if keepalives are disabled. It is only supported
1129-
on systems where the <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</>
1130-
socket option is available, and on Windows; on other systems, it has no
1131-
effect.
1128+
Unix-domain socket, or if keepalives are disabled.
1129+
It is only supported on systems where <symbol>TCP_KEEPIDLE</> or
1130+
an equivalent socket option is available, and on Windows; on other
1131+
systems, it has no effect.
11321132
</para>
11331133
</listitem>
11341134
</varlistentry>
@@ -1141,9 +1141,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
11411141
that is not acknowledged by the server should be retransmitted. A
11421142
value of zero uses the system default. This parameter is ignored for
11431143
connections made via a Unix-domain socket, or if keepalives are disabled.
1144-
It is only supported on systems where the <symbol>TCP_KEEPINTVL</>
1145-
socket option is available, and on Windows; on other systems, it has no
1146-
effect.
1144+
It is only supported on systems where <symbol>TCP_KEEPINTVL</> or
1145+
an equivalent socket option is available, and on Windows; on other
1146+
systems, it has no effect.
11471147
</para>
11481148
</listitem>
11491149
</varlistentry>
@@ -1156,8 +1156,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
11561156
client's connection to the server is considered dead. A value of
11571157
zero uses the system default. This parameter is ignored for
11581158
connections made via a Unix-domain socket, or if keepalives are disabled.
1159-
It is only supported on systems where the <symbol>TCP_KEEPCNT</>
1160-
socket option is available; on other systems, it has no effect.
1159+
It is only supported on systems where <symbol>TCP_KEEPCNT</> or
1160+
an equivalent socket option is available; on other systems, it has no
1161+
effect.
11611162
</para>
11621163
</listitem>
11631164
</varlistentry>

src/backend/libpq/pqcomm.c

+37-57
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,25 @@
9696
#include "utils/guc.h"
9797
#include "utils/memutils.h"
9898

99+
/*
100+
* Cope with the various platform-specific ways to spell TCP keepalive socket
101+
* options. This doesn't cover Windows, which as usual does its own thing.
102+
*/
103+
#if defined(TCP_KEEPIDLE)
104+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
105+
#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
106+
#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
107+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
108+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
109+
#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
110+
#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
111+
#elif defined(TCP_KEEPALIVE) && defined(__darwin__)
112+
/* TCP_KEEPALIVE is the name of this option on macOS */
113+
/* Caution: Solaris has this symbol but it means something different */
114+
#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
115+
#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
116+
#endif
117+
99118
/*
100119
* Configuration options
101120
*/
@@ -742,15 +761,15 @@ StreamConnection(pgsocket server_fd, Port *port)
742761
if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY,
743762
(char *) &on, sizeof(on)) < 0)
744763
{
745-
elog(LOG, "setsockopt(TCP_NODELAY) failed: %m");
764+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_NODELAY");
746765
return STATUS_ERROR;
747766
}
748767
#endif
749768
on = 1;
750769
if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE,
751770
(char *) &on, sizeof(on)) < 0)
752771
{
753-
elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m");
772+
elog(LOG, "setsockopt(%s) failed: %m", "SO_KEEPALIVE");
754773
return STATUS_ERROR;
755774
}
756775

@@ -781,7 +800,7 @@ StreamConnection(pgsocket server_fd, Port *port)
781800
if (getsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &oldopt,
782801
&optlen) < 0)
783802
{
784-
elog(LOG, "getsockopt(SO_SNDBUF) failed: %m");
803+
elog(LOG, "getsockopt(%s) failed: %m", "SO_SNDBUF");
785804
return STATUS_ERROR;
786805
}
787806
newopt = PQ_SEND_BUFFER_SIZE * 4;
@@ -790,7 +809,7 @@ StreamConnection(pgsocket server_fd, Port *port)
790809
if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &newopt,
791810
sizeof(newopt)) < 0)
792811
{
793-
elog(LOG, "setsockopt(SO_SNDBUF) failed: %m");
812+
elog(LOG, "setsockopt(%s) failed: %m", "SO_SNDBUF");
794813
return STATUS_ERROR;
795814
}
796815
}
@@ -1676,7 +1695,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
16761695
int
16771696
pq_getkeepalivesidle(Port *port)
16781697
{
1679-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
1698+
#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
16801699
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
16811700
return 0;
16821701

@@ -1688,34 +1707,13 @@ pq_getkeepalivesidle(Port *port)
16881707
#ifndef WIN32
16891708
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
16901709

1691-
#if defined(TCP_KEEPIDLE)
1692-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1693-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1694-
(char *) &port->default_keepalives_idle,
1695-
&size) < 0)
1696-
{
1697-
elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
1698-
port->default_keepalives_idle = -1; /* don't know */
1699-
}
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,
1710+
if (getsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
17031711
(char *) &port->default_keepalives_idle,
17041712
&size) < 0)
17051713
{
1706-
elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1714+
elog(LOG, "getsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
17071715
port->default_keepalives_idle = -1; /* don't know */
17081716
}
1709-
#else /* must have TCP_KEEPALIVE */
1710-
/* TCP_KEEPALIVE is the name of this option on macOS */
1711-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1712-
(char *) &port->default_keepalives_idle,
1713-
&size) < 0)
1714-
{
1715-
elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
1716-
port->default_keepalives_idle = -1; /* don't know */
1717-
}
1718-
#endif /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
17191717
#else /* WIN32 */
17201718
/* We can't get the defaults on Windows, so return "don't know" */
17211719
port->default_keepalives_idle = -1;
@@ -1735,7 +1733,7 @@ pq_setkeepalivesidle(int idle, Port *port)
17351733
return STATUS_OK;
17361734

17371735
/* 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)
1736+
#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
17391737
if (idle == port->keepalives_idle)
17401738
return STATUS_OK;
17411739

@@ -1754,43 +1752,25 @@ pq_setkeepalivesidle(int idle, Port *port)
17541752
if (idle == 0)
17551753
idle = port->default_keepalives_idle;
17561754

1757-
#if defined(TCP_KEEPIDLE)
1758-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1759-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1760-
(char *) &idle, sizeof(idle)) < 0)
1761-
{
1762-
elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
1763-
return STATUS_ERROR;
1764-
}
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,
1755+
if (setsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
17681756
(char *) &idle, sizeof(idle)) < 0)
17691757
{
1770-
elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1758+
elog(LOG, "setsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
17711759
return STATUS_ERROR;
17721760
}
1773-
#else /* must have TCP_KEEPALIVE */
1774-
/* TCP_KEEPALIVE is the name of this option on macOS */
1775-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1776-
(char *) &idle, sizeof(idle)) < 0)
1777-
{
1778-
elog(LOG, "setsockopt(TCP_KEEPALIVE) failed: %m");
1779-
return STATUS_ERROR;
1780-
}
1781-
#endif
17821761

17831762
port->keepalives_idle = idle;
17841763
#else /* WIN32 */
17851764
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
17861765
#endif
1787-
#else /* no way to set it */
1766+
#else
17881767
if (idle != 0)
17891768
{
17901769
elog(LOG, "setting the keepalive idle time is not supported");
17911770
return STATUS_ERROR;
17921771
}
17931772
#endif
1773+
17941774
return STATUS_OK;
17951775
}
17961776

@@ -1813,7 +1793,7 @@ pq_getkeepalivesinterval(Port *port)
18131793
(char *) &port->default_keepalives_interval,
18141794
&size) < 0)
18151795
{
1816-
elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m");
1796+
elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPINTVL");
18171797
port->default_keepalives_interval = -1; /* don't know */
18181798
}
18191799
#else
@@ -1856,7 +1836,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
18561836
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPINTVL,
18571837
(char *) &interval, sizeof(interval)) < 0)
18581838
{
1859-
elog(LOG, "setsockopt(TCP_KEEPINTVL) failed: %m");
1839+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPINTVL");
18601840
return STATUS_ERROR;
18611841
}
18621842

@@ -1867,7 +1847,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
18671847
#else
18681848
if (interval != 0)
18691849
{
1870-
elog(LOG, "setsockopt(TCP_KEEPINTVL) not supported");
1850+
elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPINTVL");
18711851
return STATUS_ERROR;
18721852
}
18731853
#endif
@@ -1893,7 +1873,7 @@ pq_getkeepalivescount(Port *port)
18931873
(char *) &port->default_keepalives_count,
18941874
&size) < 0)
18951875
{
1896-
elog(LOG, "getsockopt(TCP_KEEPCNT) failed: %m");
1876+
elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPCNT");
18971877
port->default_keepalives_count = -1; /* don't know */
18981878
}
18991879
}
@@ -1931,15 +1911,15 @@ pq_setkeepalivescount(int count, Port *port)
19311911
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPCNT,
19321912
(char *) &count, sizeof(count)) < 0)
19331913
{
1934-
elog(LOG, "setsockopt(TCP_KEEPCNT) failed: %m");
1914+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPCNT");
19351915
return STATUS_ERROR;
19361916
}
19371917

19381918
port->keepalives_count = count;
19391919
#else
19401920
if (count != 0)
19411921
{
1942-
elog(LOG, "setsockopt(TCP_KEEPCNT) not supported");
1922+
elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPCNT");
19431923
return STATUS_ERROR;
19441924
}
19451925
#endif

src/interfaces/libpq/fe-connect.c

+29-31
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,25 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
9494
/* This too */
9595
#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
9696

97+
/*
98+
* Cope with the various platform-specific ways to spell TCP keepalive socket
99+
* options. This doesn't cover Windows, which as usual does its own thing.
100+
*/
101+
#if defined(TCP_KEEPIDLE)
102+
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
103+
#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
104+
#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
105+
#elif defined(TCP_KEEPALIVE_THRESHOLD)
106+
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
107+
#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
108+
#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
109+
#elif defined(TCP_KEEPALIVE) && defined(__darwin__)
110+
/* TCP_KEEPALIVE is the name of this option on macOS */
111+
/* Caution: Solaris has this symbol but it means something different */
112+
#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
113+
#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
114+
#endif
115+
97116
/*
98117
* fall back options if they are not specified by arguments or defined
99118
* by environment variables
@@ -1470,39 +1489,15 @@ setKeepalivesIdle(PGconn *conn)
14701489
if (idle < 0)
14711490
idle = 0;
14721491

1473-
#if defined(TCP_KEEPIDLE)
1474-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1475-
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1476-
(char *) &idle, sizeof(idle)) < 0)
1477-
{
1478-
char sebuf[256];
1479-
1480-
appendPQExpBuffer(&conn->errorMessage,
1481-
libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"),
1482-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1483-
return 0;
1484-
}
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 */
1499-
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1492+
#ifdef PG_TCP_KEEPALIVE_IDLE
1493+
if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
15001494
(char *) &idle, sizeof(idle)) < 0)
15011495
{
15021496
char sebuf[256];
15031497

15041498
appendPQExpBuffer(&conn->errorMessage,
1505-
libpq_gettext("setsockopt(TCP_KEEPALIVE) failed: %s\n"),
1499+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1500+
PG_TCP_KEEPALIVE_IDLE_STR,
15061501
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
15071502
return 0;
15081503
}
@@ -1533,7 +1528,8 @@ setKeepalivesInterval(PGconn *conn)
15331528
char sebuf[256];
15341529

15351530
appendPQExpBuffer(&conn->errorMessage,
1536-
libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"),
1531+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1532+
"TCP_KEEPINTVL",
15371533
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
15381534
return 0;
15391535
}
@@ -1565,7 +1561,8 @@ setKeepalivesCount(PGconn *conn)
15651561
char sebuf[256];
15661562

15671563
appendPQExpBuffer(&conn->errorMessage,
1568-
libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"),
1564+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1565+
"TCP_KEEPCNT",
15691566
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
15701567
return 0;
15711568
}
@@ -2123,7 +2120,8 @@ PQconnectPoll(PGconn *conn)
21232120
(char *) &on, sizeof(on)) < 0)
21242121
{
21252122
appendPQExpBuffer(&conn->errorMessage,
2126-
libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"),
2123+
libpq_gettext("setsockopt(%s) failed: %s\n"),
2124+
"SO_KEEPALIVE",
21272125
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
21282126
err = 1;
21292127
}

0 commit comments

Comments
 (0)