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

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
@@ -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

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
*/
@@ -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

Lines changed: 29 additions & 31 deletions
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)
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