Skip to content

Commit 43c67e3

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 a2de017 commit 43c67e3

File tree

4 files changed

+86
-106
lines changed

4 files changed

+86
-106
lines changed

doc/src/sgml/config.sgml

Lines changed: 10 additions & 9 deletions
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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,10 +1073,10 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10731073
Controls the number of seconds of inactivity after which TCP should
10741074
send a keepalive message to the server. A value of zero uses the
10751075
system default. This parameter is ignored for connections made via a
1076-
Unix-domain socket, or if keepalives are disabled. It is only supported
1077-
on systems where the <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</>
1078-
socket option is available, and on Windows; on other systems, it has no
1079-
effect.
1076+
Unix-domain socket, or if keepalives are disabled.
1077+
It is only supported on systems where <symbol>TCP_KEEPIDLE</> or
1078+
an equivalent socket option is available, and on Windows; on other
1079+
systems, it has no effect.
10801080
</para>
10811081
</listitem>
10821082
</varlistentry>
@@ -1089,9 +1089,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10891089
that is not acknowledged by the server should be retransmitted. A
10901090
value of zero uses the system default. This parameter is ignored for
10911091
connections made via a Unix-domain socket, or if keepalives are disabled.
1092-
It is only supported on systems where the <symbol>TCP_KEEPINTVL</>
1093-
socket option is available, and on Windows; on other systems, it has no
1094-
effect.
1092+
It is only supported on systems where <symbol>TCP_KEEPINTVL</> or
1093+
an equivalent socket option is available, and on Windows; on other
1094+
systems, it has no effect.
10951095
</para>
10961096
</listitem>
10971097
</varlistentry>
@@ -1104,8 +1104,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
11041104
client's connection to the server is considered dead. A value of
11051105
zero uses the system default. This parameter is ignored for
11061106
connections made via a Unix-domain socket, or if keepalives are disabled.
1107-
It is only supported on systems where the <symbol>TCP_KEEPCNT</>
1108-
socket option is available; on other systems, it has no effect.
1107+
It is only supported on systems where <symbol>TCP_KEEPCNT</> or
1108+
an equivalent socket option is available; on other systems, it has no
1109+
effect.
11091110
</para>
11101111
</listitem>
11111112
</varlistentry>

src/backend/libpq/pqcomm.c

Lines changed: 37 additions & 57 deletions
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
*/
@@ -719,15 +738,15 @@ StreamConnection(pgsocket server_fd, Port *port)
719738
if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY,
720739
(char *) &on, sizeof(on)) < 0)
721740
{
722-
elog(LOG, "setsockopt(TCP_NODELAY) failed: %m");
741+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_NODELAY");
723742
return STATUS_ERROR;
724743
}
725744
#endif
726745
on = 1;
727746
if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE,
728747
(char *) &on, sizeof(on)) < 0)
729748
{
730-
elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m");
749+
elog(LOG, "setsockopt(%s) failed: %m", "SO_KEEPALIVE");
731750
return STATUS_ERROR;
732751
}
733752

@@ -758,7 +777,7 @@ StreamConnection(pgsocket server_fd, Port *port)
758777
if (getsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &oldopt,
759778
&optlen) < 0)
760779
{
761-
elog(LOG, "getsockopt(SO_SNDBUF) failed: %m");
780+
elog(LOG, "getsockopt(%s) failed: %m", "SO_SNDBUF");
762781
return STATUS_ERROR;
763782
}
764783
newopt = PQ_SEND_BUFFER_SIZE * 4;
@@ -767,7 +786,7 @@ StreamConnection(pgsocket server_fd, Port *port)
767786
if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &newopt,
768787
sizeof(newopt)) < 0)
769788
{
770-
elog(LOG, "setsockopt(SO_SNDBUF) failed: %m");
789+
elog(LOG, "setsockopt(%s) failed: %m", "SO_SNDBUF");
771790
return STATUS_ERROR;
772791
}
773792
}
@@ -1653,7 +1672,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
16531672
int
16541673
pq_getkeepalivesidle(Port *port)
16551674
{
1656-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
1675+
#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
16571676
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
16581677
return 0;
16591678

@@ -1665,34 +1684,13 @@ pq_getkeepalivesidle(Port *port)
16651684
#ifndef WIN32
16661685
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
16671686

1668-
#if defined(TCP_KEEPIDLE)
1669-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1670-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1671-
(char *) &port->default_keepalives_idle,
1672-
&size) < 0)
1673-
{
1674-
elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
1675-
port->default_keepalives_idle = -1; /* don't know */
1676-
}
1677-
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1678-
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1679-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1687+
if (getsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
16801688
(char *) &port->default_keepalives_idle,
16811689
&size) < 0)
16821690
{
1683-
elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1691+
elog(LOG, "getsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
16841692
port->default_keepalives_idle = -1; /* don't know */
16851693
}
1686-
#else /* must have TCP_KEEPALIVE */
1687-
/* TCP_KEEPALIVE is the name of this option on macOS */
1688-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1689-
(char *) &port->default_keepalives_idle,
1690-
&size) < 0)
1691-
{
1692-
elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
1693-
port->default_keepalives_idle = -1; /* don't know */
1694-
}
1695-
#endif /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
16961694
#else /* WIN32 */
16971695
/* We can't get the defaults on Windows, so return "don't know" */
16981696
port->default_keepalives_idle = -1;
@@ -1712,7 +1710,7 @@ pq_setkeepalivesidle(int idle, Port *port)
17121710
return STATUS_OK;
17131711

17141712
/* check SIO_KEEPALIVE_VALS here, not just WIN32, as some toolchains lack it */
1715-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
1713+
#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
17161714
if (idle == port->keepalives_idle)
17171715
return STATUS_OK;
17181716

@@ -1731,43 +1729,25 @@ pq_setkeepalivesidle(int idle, Port *port)
17311729
if (idle == 0)
17321730
idle = port->default_keepalives_idle;
17331731

1734-
#if defined(TCP_KEEPIDLE)
1735-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1736-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1737-
(char *) &idle, sizeof(idle)) < 0)
1738-
{
1739-
elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
1740-
return STATUS_ERROR;
1741-
}
1742-
#elif defined(TCP_KEEPALIVE_THRESHOLD)
1743-
/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
1744-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
1732+
if (setsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
17451733
(char *) &idle, sizeof(idle)) < 0)
17461734
{
1747-
elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1735+
elog(LOG, "setsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
17481736
return STATUS_ERROR;
17491737
}
1750-
#else /* must have TCP_KEEPALIVE */
1751-
/* TCP_KEEPALIVE is the name of this option on macOS */
1752-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1753-
(char *) &idle, sizeof(idle)) < 0)
1754-
{
1755-
elog(LOG, "setsockopt(TCP_KEEPALIVE) failed: %m");
1756-
return STATUS_ERROR;
1757-
}
1758-
#endif
17591738

17601739
port->keepalives_idle = idle;
17611740
#else /* WIN32 */
17621741
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
17631742
#endif
1764-
#else /* no way to set it */
1743+
#else
17651744
if (idle != 0)
17661745
{
17671746
elog(LOG, "setting the keepalive idle time is not supported");
17681747
return STATUS_ERROR;
17691748
}
17701749
#endif
1750+
17711751
return STATUS_OK;
17721752
}
17731753

@@ -1790,7 +1770,7 @@ pq_getkeepalivesinterval(Port *port)
17901770
(char *) &port->default_keepalives_interval,
17911771
&size) < 0)
17921772
{
1793-
elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m");
1773+
elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPINTVL");
17941774
port->default_keepalives_interval = -1; /* don't know */
17951775
}
17961776
#else
@@ -1833,7 +1813,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
18331813
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPINTVL,
18341814
(char *) &interval, sizeof(interval)) < 0)
18351815
{
1836-
elog(LOG, "setsockopt(TCP_KEEPINTVL) failed: %m");
1816+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPINTVL");
18371817
return STATUS_ERROR;
18381818
}
18391819

@@ -1844,7 +1824,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
18441824
#else
18451825
if (interval != 0)
18461826
{
1847-
elog(LOG, "setsockopt(TCP_KEEPINTVL) not supported");
1827+
elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPINTVL");
18481828
return STATUS_ERROR;
18491829
}
18501830
#endif
@@ -1870,7 +1850,7 @@ pq_getkeepalivescount(Port *port)
18701850
(char *) &port->default_keepalives_count,
18711851
&size) < 0)
18721852
{
1873-
elog(LOG, "getsockopt(TCP_KEEPCNT) failed: %m");
1853+
elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPCNT");
18741854
port->default_keepalives_count = -1; /* don't know */
18751855
}
18761856
}
@@ -1908,15 +1888,15 @@ pq_setkeepalivescount(int count, Port *port)
19081888
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPCNT,
19091889
(char *) &count, sizeof(count)) < 0)
19101890
{
1911-
elog(LOG, "setsockopt(TCP_KEEPCNT) failed: %m");
1891+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPCNT");
19121892
return STATUS_ERROR;
19131893
}
19141894

19151895
port->keepalives_count = count;
19161896
#else
19171897
if (count != 0)
19181898
{
1919-
elog(LOG, "setsockopt(TCP_KEEPCNT) not supported");
1899+
elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPCNT");
19201900
return STATUS_ERROR;
19211901
}
19221902
#endif

src/interfaces/libpq/fe-connect.c

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,25 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
9999
/* This too */
100100
#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
101101

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

1283-
#if defined(TCP_KEEPIDLE)
1284-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1285-
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1286-
(char *) &idle, sizeof(idle)) < 0)
1287-
{
1288-
char sebuf[256];
1289-
1290-
appendPQExpBuffer(&conn->errorMessage,
1291-
libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"),
1292-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1293-
return 0;
1294-
}
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 */
1309-
if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1302+
#ifdef PG_TCP_KEEPALIVE_IDLE
1303+
if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
13101304
(char *) &idle, sizeof(idle)) < 0)
13111305
{
13121306
char sebuf[256];
13131307

13141308
appendPQExpBuffer(&conn->errorMessage,
1315-
libpq_gettext("setsockopt(TCP_KEEPALIVE) failed: %s\n"),
1309+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1310+
PG_TCP_KEEPALIVE_IDLE_STR,
13161311
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
13171312
return 0;
13181313
}
@@ -1343,7 +1338,8 @@ setKeepalivesInterval(PGconn *conn)
13431338
char sebuf[256];
13441339

13451340
appendPQExpBuffer(&conn->errorMessage,
1346-
libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"),
1341+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1342+
"TCP_KEEPINTVL",
13471343
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
13481344
return 0;
13491345
}
@@ -1375,7 +1371,8 @@ setKeepalivesCount(PGconn *conn)
13751371
char sebuf[256];
13761372

13771373
appendPQExpBuffer(&conn->errorMessage,
1378-
libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"),
1374+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1375+
"TCP_KEEPCNT",
13791376
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
13801377
return 0;
13811378
}
@@ -1841,7 +1838,8 @@ PQconnectPoll(PGconn *conn)
18411838
(char *) &on, sizeof(on)) < 0)
18421839
{
18431840
appendPQExpBuffer(&conn->errorMessage,
1844-
libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"),
1841+
libpq_gettext("setsockopt(%s) failed: %s\n"),
1842+
"SO_KEEPALIVE",
18451843
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
18461844
err = 1;
18471845
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy