Skip to content

Commit cc154d9

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 9ce7f39 commit cc154d9

File tree

4 files changed

+88
-106
lines changed

4 files changed

+88
-106
lines changed

doc/src/sgml/config.sgml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,8 @@ include 'filename'
677677
<para>
678678
Specifies the number of seconds before sending a keepalive packet on
679679
an otherwise idle connection. A value of 0 uses the system default.
680-
This parameter is supported only on systems that support the
681-
<symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</> symbols, and on
680+
This parameter is supported only on systems that support
681+
<symbol>TCP_KEEPIDLE</> or an equivalent socket option, and on
682682
Windows; on other systems, it must be zero.
683683
In sessions connected via a Unix-domain socket, this parameter is
684684
ignored and always reads as zero.
@@ -701,9 +701,9 @@ include 'filename'
701701
<para>
702702
Specifies the number of seconds between sending keepalives on an
703703
otherwise idle connection. A value of 0 uses the system default.
704-
This parameter is supported only on systems that support the
705-
<symbol>TCP_KEEPINTVL</> symbol, and on Windows; on other systems, it
706-
must be zero.
704+
This parameter is supported only on systems that support
705+
<symbol>TCP_KEEPINTVL</> or an equivalent socket option, and on
706+
Windows; on other systems, it must be zero.
707707
In sessions connected via a Unix-domain socket, this parameter is
708708
ignored and always reads as zero.
709709
</para>
@@ -724,9 +724,10 @@ include 'filename'
724724
<listitem>
725725
<para>
726726
Specifies the number of keepalive packets to send on an otherwise idle
727-
connection. A value of 0 uses the system default. This parameter is
728-
supported only on systems that support the <symbol>TCP_KEEPCNT</>
729-
symbol; on other systems, it must be zero.
727+
connection. A value of 0 uses the system default.
728+
This parameter is supported only on systems that support
729+
<symbol>TCP_KEEPCNT</> or an equivalent socket option;
730+
on other systems, it must be zero.
730731
In sessions connected via a Unix-domain socket, this parameter is
731732
ignored and always reads as zero.
732733
</para>

doc/src/sgml/libpq.sgml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,10 +1069,10 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10691069
Controls the number of seconds of inactivity after which TCP should
10701070
send a keepalive message to the server. A value of zero uses the
10711071
system default. This parameter is ignored for connections made via a
1072-
Unix-domain socket, or if keepalives are disabled. It is only supported
1073-
on systems where the <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</>
1074-
socket option is available, and on Windows; on other systems, it has no
1075-
effect.
1072+
Unix-domain socket, or if keepalives are disabled.
1073+
It is only supported on systems where <symbol>TCP_KEEPIDLE</> or
1074+
an equivalent socket option is available, and on Windows; on other
1075+
systems, it has no effect.
10761076
</para>
10771077
</listitem>
10781078
</varlistentry>
@@ -1085,9 +1085,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10851085
that is not acknowledged by the server should be retransmitted. A
10861086
value of zero uses the system default. This parameter is ignored for
10871087
connections made via a Unix-domain socket, or if keepalives are disabled.
1088-
It is only supported on systems where the <symbol>TCP_KEEPINTVL</>
1089-
socket option is available, and on Windows; on other systems, it has no
1090-
effect.
1088+
It is only supported on systems where <symbol>TCP_KEEPINTVL</> or
1089+
an equivalent socket option is available, and on Windows; on other
1090+
systems, it has no effect.
10911091
</para>
10921092
</listitem>
10931093
</varlistentry>
@@ -1100,8 +1100,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
11001100
client's connection to the server is considered dead. A value of
11011101
zero uses the system default. This parameter is ignored for
11021102
connections made via a Unix-domain socket, or if keepalives are disabled.
1103-
It is only supported on systems where the <symbol>TCP_KEEPCNT</>
1104-
socket option is available; on other systems, it has no effect.
1103+
It is only supported on systems where <symbol>TCP_KEEPCNT</> or
1104+
an equivalent socket option is available; on other systems, it has no
1105+
effect.
11051106
</para>
11061107
</listitem>
11071108
</varlistentry>

src/backend/libpq/pqcomm.c

Lines changed: 40 additions & 58 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
*/
@@ -415,7 +434,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
415434
{
416435
ereport(LOG,
417436
(errcode_for_socket_access(),
418-
errmsg("setsockopt(SO_REUSEADDR) failed: %m")));
437+
errmsg("setsockopt(%s) failed: %m",
438+
"SO_REUSEADDR")));
419439
closesocket(fd);
420440
continue;
421441
}
@@ -430,7 +450,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
430450
{
431451
ereport(LOG,
432452
(errcode_for_socket_access(),
433-
errmsg("setsockopt(IPV6_V6ONLY) failed: %m")));
453+
errmsg("setsockopt(%s) failed: %m",
454+
"IPV6_V6ONLY")));
434455
closesocket(fd);
435456
continue;
436457
}
@@ -667,15 +688,15 @@ StreamConnection(pgsocket server_fd, Port *port)
667688
if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY,
668689
(char *) &on, sizeof(on)) < 0)
669690
{
670-
elog(LOG, "setsockopt(TCP_NODELAY) failed: %m");
691+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_NODELAY");
671692
return STATUS_ERROR;
672693
}
673694
#endif
674695
on = 1;
675696
if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE,
676697
(char *) &on, sizeof(on)) < 0)
677698
{
678-
elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m");
699+
elog(LOG, "setsockopt(%s) failed: %m", "SO_KEEPALIVE");
679700
return STATUS_ERROR;
680701
}
681702

@@ -689,7 +710,7 @@ StreamConnection(pgsocket server_fd, Port *port)
689710
if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &on,
690711
sizeof(on)) < 0)
691712
{
692-
elog(LOG, "setsockopt(SO_SNDBUF) failed: %m");
713+
elog(LOG, "setsockopt(%s) failed: %m", "SO_SNDBUF");
693714
return STATUS_ERROR;
694715
}
695716
#endif
@@ -1593,7 +1614,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
15931614
int
15941615
pq_getkeepalivesidle(Port *port)
15951616
{
1596-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
1617+
#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
15971618
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
15981619
return 0;
15991620

@@ -1605,34 +1626,13 @@ pq_getkeepalivesidle(Port *port)
16051626
#ifndef WIN32
16061627
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
16071628

1608-
#if defined(TCP_KEEPIDLE)
1609-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1610-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1611-
(char *) &port->default_keepalives_idle,
1612-
&size) < 0)
1613-
{
1614-
elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
1615-
port->default_keepalives_idle = -1; /* don't know */
1616-
}
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,
1629+
if (getsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
16201630
(char *) &port->default_keepalives_idle,
16211631
&size) < 0)
16221632
{
1623-
elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1633+
elog(LOG, "getsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
16241634
port->default_keepalives_idle = -1; /* don't know */
16251635
}
1626-
#else /* must have TCP_KEEPALIVE */
1627-
/* TCP_KEEPALIVE is the name of this option on macOS */
1628-
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1629-
(char *) &port->default_keepalives_idle,
1630-
&size) < 0)
1631-
{
1632-
elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
1633-
port->default_keepalives_idle = -1; /* don't know */
1634-
}
1635-
#endif /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
16361636
#else /* WIN32 */
16371637
/* We can't get the defaults on Windows, so return "don't know" */
16381638
port->default_keepalives_idle = -1;
@@ -1652,7 +1652,7 @@ pq_setkeepalivesidle(int idle, Port *port)
16521652
return STATUS_OK;
16531653

16541654
/* 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)
1655+
#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
16561656
if (idle == port->keepalives_idle)
16571657
return STATUS_OK;
16581658

@@ -1671,43 +1671,25 @@ pq_setkeepalivesidle(int idle, Port *port)
16711671
if (idle == 0)
16721672
idle = port->default_keepalives_idle;
16731673

1674-
#if defined(TCP_KEEPIDLE)
1675-
/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
1676-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
1677-
(char *) &idle, sizeof(idle)) < 0)
1678-
{
1679-
elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
1680-
return STATUS_ERROR;
1681-
}
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,
1674+
if (setsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
16851675
(char *) &idle, sizeof(idle)) < 0)
16861676
{
1687-
elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
1677+
elog(LOG, "setsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
16881678
return STATUS_ERROR;
16891679
}
1690-
#else /* must have TCP_KEEPALIVE */
1691-
/* TCP_KEEPALIVE is the name of this option on macOS */
1692-
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
1693-
(char *) &idle, sizeof(idle)) < 0)
1694-
{
1695-
elog(LOG, "setsockopt(TCP_KEEPALIVE) failed: %m");
1696-
return STATUS_ERROR;
1697-
}
1698-
#endif
16991680

17001681
port->keepalives_idle = idle;
17011682
#else /* WIN32 */
17021683
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
17031684
#endif
1704-
#else /* no way to set it */
1685+
#else
17051686
if (idle != 0)
17061687
{
17071688
elog(LOG, "setting the keepalive idle time is not supported");
17081689
return STATUS_ERROR;
17091690
}
17101691
#endif
1692+
17111693
return STATUS_OK;
17121694
}
17131695

@@ -1730,7 +1712,7 @@ pq_getkeepalivesinterval(Port *port)
17301712
(char *) &port->default_keepalives_interval,
17311713
&size) < 0)
17321714
{
1733-
elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m");
1715+
elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPINTVL");
17341716
port->default_keepalives_interval = -1; /* don't know */
17351717
}
17361718
#else
@@ -1773,7 +1755,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
17731755
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPINTVL,
17741756
(char *) &interval, sizeof(interval)) < 0)
17751757
{
1776-
elog(LOG, "setsockopt(TCP_KEEPINTVL) failed: %m");
1758+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPINTVL");
17771759
return STATUS_ERROR;
17781760
}
17791761

@@ -1784,7 +1766,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
17841766
#else
17851767
if (interval != 0)
17861768
{
1787-
elog(LOG, "setsockopt(TCP_KEEPINTVL) not supported");
1769+
elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPINTVL");
17881770
return STATUS_ERROR;
17891771
}
17901772
#endif
@@ -1810,7 +1792,7 @@ pq_getkeepalivescount(Port *port)
18101792
(char *) &port->default_keepalives_count,
18111793
&size) < 0)
18121794
{
1813-
elog(LOG, "getsockopt(TCP_KEEPCNT) failed: %m");
1795+
elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPCNT");
18141796
port->default_keepalives_count = -1; /* don't know */
18151797
}
18161798
}
@@ -1848,15 +1830,15 @@ pq_setkeepalivescount(int count, Port *port)
18481830
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPCNT,
18491831
(char *) &count, sizeof(count)) < 0)
18501832
{
1851-
elog(LOG, "setsockopt(TCP_KEEPCNT) failed: %m");
1833+
elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPCNT");
18521834
return STATUS_ERROR;
18531835
}
18541836

18551837
port->keepalives_count = count;
18561838
#else
18571839
if (count != 0)
18581840
{
1859-
elog(LOG, "setsockopt(TCP_KEEPCNT) not supported");
1841+
elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPCNT");
18601842
return STATUS_ERROR;
18611843
}
18621844
#endif

0 commit comments

Comments
 (0)