diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d2526a1bd3e..cac5c04111f 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -593,8 +593,8 @@ SET ENABLE_SEQSCAN TO OFF;
Specifies the number of seconds before sending a keepalive packet on
an otherwise idle connection. A value of 0 uses the system default.
- This parameter is supported only on systems that support the
- TCP_KEEPIDLE> or TCP_KEEPALIVE> symbols, and on
+ This parameter is supported only on systems that support
+ TCP_KEEPIDLE> or an equivalent socket option, and on
Windows; on other systems, it must be zero.
In sessions connected via a Unix-domain socket, this parameter is
ignored and always reads as zero.
@@ -617,9 +617,9 @@ SET ENABLE_SEQSCAN TO OFF;
Specifies the number of seconds between sending keepalives on an
otherwise idle connection. A value of 0 uses the system default.
- This parameter is supported only on systems that support the
- TCP_KEEPINTVL> symbol, and on Windows; on other systems, it
- must be zero.
+ This parameter is supported only on systems that support
+ TCP_KEEPINTVL> or an equivalent socket option, and on
+ Windows; on other systems, it must be zero.
In sessions connected via a Unix-domain socket, this parameter is
ignored and always reads as zero.
@@ -640,9 +640,10 @@ SET ENABLE_SEQSCAN TO OFF;
Specifies the number of keepalive packets to send on an otherwise idle
- connection. A value of 0 uses the system default. This parameter is
- supported only on systems that support the TCP_KEEPCNT>
- symbol; on other systems, it must be zero.
+ connection. A value of 0 uses the system default.
+ This parameter is supported only on systems that support
+ TCP_KEEPCNT> or an equivalent socket option;
+ on other systems, it must be zero.
In sessions connected via a Unix-domain socket, this parameter is
ignored and always reads as zero.
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a6ef9844ccc..2412d3abd5f 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1043,10 +1043,10 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
Controls the number of seconds of inactivity after which TCP should
send a keepalive message to the server. A value of zero uses the
system default. This parameter is ignored for connections made via a
- Unix-domain socket, or if keepalives are disabled. It is only supported
- on systems where the TCP_KEEPIDLE> or TCP_KEEPALIVE>
- socket option is available, and on Windows; on other systems, it has no
- effect.
+ Unix-domain socket, or if keepalives are disabled.
+ It is only supported on systems where TCP_KEEPIDLE> or
+ an equivalent socket option is available, and on Windows; on other
+ systems, it has no effect.
@@ -1059,9 +1059,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
that is not acknowledged by the server should be retransmitted. A
value of zero uses the system default. This parameter is ignored for
connections made via a Unix-domain socket, or if keepalives are disabled.
- It is only supported on systems where the TCP_KEEPINTVL>
- socket option is available, and on Windows; on other systems, it has no
- effect.
+ It is only supported on systems where TCP_KEEPINTVL> or
+ an equivalent socket option is available, and on Windows; on other
+ systems, it has no effect.
@@ -1074,8 +1074,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
client's connection to the server is considered dead. A value of
zero uses the system default. This parameter is ignored for
connections made via a Unix-domain socket, or if keepalives are disabled.
- It is only supported on systems where the TCP_KEEPCNT>
- socket option is available; on other systems, it has no effect.
+ It is only supported on systems where TCP_KEEPCNT> or
+ an equivalent socket option is available; on other systems, it has no
+ effect.
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 17406d1e722..4da2849b10d 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -96,6 +96,25 @@
#include "utils/guc.h"
#include "utils/memutils.h"
+/*
+ * Cope with the various platform-specific ways to spell TCP keepalive socket
+ * options. This doesn't cover Windows, which as usual does its own thing.
+ */
+#if defined(TCP_KEEPIDLE)
+/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
+#elif defined(TCP_KEEPALIVE) && defined(__darwin__)
+/* TCP_KEEPALIVE is the name of this option on macOS */
+/* Caution: Solaris has this symbol but it means something different */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
+#endif
+
/*
* Configuration options
*/
@@ -408,7 +427,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
{
ereport(LOG,
(errcode_for_socket_access(),
- errmsg("setsockopt(SO_REUSEADDR) failed: %m")));
+ errmsg("setsockopt(%s) failed: %m",
+ "SO_REUSEADDR")));
closesocket(fd);
continue;
}
@@ -423,7 +443,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
{
ereport(LOG,
(errcode_for_socket_access(),
- errmsg("setsockopt(IPV6_V6ONLY) failed: %m")));
+ errmsg("setsockopt(%s) failed: %m",
+ "IPV6_V6ONLY")));
closesocket(fd);
continue;
}
@@ -668,7 +689,7 @@ StreamConnection(pgsocket server_fd, Port *port)
if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY,
(char *) &on, sizeof(on)) < 0)
{
- elog(LOG, "setsockopt(TCP_NODELAY) failed: %m");
+ elog(LOG, "setsockopt(%s) failed: %m", "TCP_NODELAY");
return STATUS_ERROR;
}
#endif
@@ -676,7 +697,7 @@ StreamConnection(pgsocket server_fd, Port *port)
if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE,
(char *) &on, sizeof(on)) < 0)
{
- elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m");
+ elog(LOG, "setsockopt(%s) failed: %m", "SO_KEEPALIVE");
return STATUS_ERROR;
}
@@ -690,7 +711,7 @@ StreamConnection(pgsocket server_fd, Port *port)
if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &on,
sizeof(on)) < 0)
{
- elog(LOG, "setsockopt(SO_SNDBUF) failed: %m");
+ elog(LOG, "setsockopt(%s) failed: %m", "SO_SNDBUF");
return STATUS_ERROR;
}
#endif
@@ -1570,7 +1591,7 @@ pq_setkeepaliveswin32(Port *port, int idle, int interval)
int
pq_getkeepalivesidle(Port *port)
{
-#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(WIN32)
+#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
return 0;
@@ -1582,34 +1603,13 @@ pq_getkeepalivesidle(Port *port)
#ifndef WIN32
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
-#if defined(TCP_KEEPIDLE)
- /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
- if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
+ if (getsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
(char *) &port->default_keepalives_idle,
&size) < 0)
{
- elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
+ elog(LOG, "getsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
port->default_keepalives_idle = -1; /* don't know */
}
-#elif defined(TCP_KEEPALIVE_THRESHOLD)
- /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
- if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
- (char *) &port->default_keepalives_idle,
- &size) < 0)
- {
- elog(LOG, "getsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
- port->default_keepalives_idle = -1; /* don't know */
- }
-#else /* must have TCP_KEEPALIVE */
- /* TCP_KEEPALIVE is the name of this option on macOS */
- if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
- (char *) &port->default_keepalives_idle,
- &size) < 0)
- {
- elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
- port->default_keepalives_idle = -1; /* don't know */
- }
-#endif /* KEEPIDLE/KEEPALIVE_THRESHOLD/KEEPALIVE */
#else /* WIN32 */
/* We can't get the defaults on Windows, so return "don't know" */
port->default_keepalives_idle = -1;
@@ -1629,7 +1629,7 @@ pq_setkeepalivesidle(int idle, Port *port)
return STATUS_OK;
/* check SIO_KEEPALIVE_VALS here, not just WIN32, as some toolchains lack it */
-#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE_THRESHOLD) || defined(TCP_KEEPALIVE) || defined(SIO_KEEPALIVE_VALS)
+#if defined(PG_TCP_KEEPALIVE_IDLE) || defined(SIO_KEEPALIVE_VALS)
if (idle == port->keepalives_idle)
return STATUS_OK;
@@ -1648,43 +1648,25 @@ pq_setkeepalivesidle(int idle, Port *port)
if (idle == 0)
idle = port->default_keepalives_idle;
-#if defined(TCP_KEEPIDLE)
- /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
- if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPIDLE,
+ if (setsockopt(port->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
(char *) &idle, sizeof(idle)) < 0)
{
- elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
+ elog(LOG, "setsockopt(%s) failed: %m", PG_TCP_KEEPALIVE_IDLE_STR);
return STATUS_ERROR;
}
-#elif defined(TCP_KEEPALIVE_THRESHOLD)
- /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
- if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
- (char *) &idle, sizeof(idle)) < 0)
- {
- elog(LOG, "setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %m");
- return STATUS_ERROR;
- }
-#else /* must have TCP_KEEPALIVE */
- /* TCP_KEEPALIVE is the name of this option on macOS */
- if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPALIVE,
- (char *) &idle, sizeof(idle)) < 0)
- {
- elog(LOG, "setsockopt(TCP_KEEPALIVE) failed: %m");
- return STATUS_ERROR;
- }
-#endif
port->keepalives_idle = idle;
#else /* WIN32 */
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
#endif
-#else /* no way to set it */
+#else
if (idle != 0)
{
elog(LOG, "setting the keepalive idle time is not supported");
return STATUS_ERROR;
}
#endif
+
return STATUS_OK;
}
@@ -1707,7 +1689,7 @@ pq_getkeepalivesinterval(Port *port)
(char *) &port->default_keepalives_interval,
&size) < 0)
{
- elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m");
+ elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPINTVL");
port->default_keepalives_interval = -1; /* don't know */
}
#else
@@ -1750,7 +1732,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPINTVL,
(char *) &interval, sizeof(interval)) < 0)
{
- elog(LOG, "setsockopt(TCP_KEEPINTVL) failed: %m");
+ elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPINTVL");
return STATUS_ERROR;
}
@@ -1761,7 +1743,7 @@ pq_setkeepalivesinterval(int interval, Port *port)
#else
if (interval != 0)
{
- elog(LOG, "setsockopt(TCP_KEEPINTVL) not supported");
+ elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPINTVL");
return STATUS_ERROR;
}
#endif
@@ -1787,7 +1769,7 @@ pq_getkeepalivescount(Port *port)
(char *) &port->default_keepalives_count,
&size) < 0)
{
- elog(LOG, "getsockopt(TCP_KEEPCNT) failed: %m");
+ elog(LOG, "getsockopt(%s) failed: %m", "TCP_KEEPCNT");
port->default_keepalives_count = -1; /* don't know */
}
}
@@ -1825,7 +1807,7 @@ pq_setkeepalivescount(int count, Port *port)
if (setsockopt(port->sock, IPPROTO_TCP, TCP_KEEPCNT,
(char *) &count, sizeof(count)) < 0)
{
- elog(LOG, "setsockopt(TCP_KEEPCNT) failed: %m");
+ elog(LOG, "setsockopt(%s) failed: %m", "TCP_KEEPCNT");
return STATUS_ERROR;
}
@@ -1833,7 +1815,7 @@ pq_setkeepalivescount(int count, Port *port)
#else
if (count != 0)
{
- elog(LOG, "setsockopt(TCP_KEEPCNT) not supported");
+ elog(LOG, "setsockopt(%s) not supported", "TCP_KEEPCNT");
return STATUS_ERROR;
}
#endif
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 4a71ddcf422..1e10375a2e2 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -99,6 +99,25 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* This too */
#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
+/*
+ * Cope with the various platform-specific ways to spell TCP keepalive socket
+ * options. This doesn't cover Windows, which as usual does its own thing.
+ */
+#if defined(TCP_KEEPIDLE)
+/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
+#elif defined(TCP_KEEPALIVE) && defined(__darwin__)
+/* TCP_KEEPALIVE is the name of this option on macOS */
+/* Caution: Solaris has this symbol but it means something different */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
+#endif
+
/*
* fall back options if they are not specified by arguments or defined
* by environment variables
@@ -1192,39 +1211,15 @@ setKeepalivesIdle(PGconn *conn)
if (idle < 0)
idle = 0;
-#if defined(TCP_KEEPIDLE)
- /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
- if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
+#ifdef PG_TCP_KEEPALIVE_IDLE
+ if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
(char *) &idle, sizeof(idle)) < 0)
{
char sebuf[256];
appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- return 0;
- }
-#elif defined(TCP_KEEPALIVE_THRESHOLD)
- /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris */
- if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
- (char *) &idle, sizeof(idle)) < 0)
- {
- char sebuf[256];
-
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(TCP_KEEPALIVE_THRESHOLD) failed: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- return 0;
- }
-#elif defined(TCP_KEEPALIVE)
- /* TCP_KEEPALIVE is the name of this option on macOS */
- if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
- (char *) &idle, sizeof(idle)) < 0)
- {
- char sebuf[256];
-
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(TCP_KEEPALIVE) failed: %s\n"),
+ libpq_gettext("setsockopt(%s) failed: %s\n"),
+ PG_TCP_KEEPALIVE_IDLE_STR,
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
@@ -1255,7 +1250,8 @@ setKeepalivesInterval(PGconn *conn)
char sebuf[256];
appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"),
+ libpq_gettext("setsockopt(%s) failed: %s\n"),
+ "TCP_KEEPINTVL",
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
@@ -1287,7 +1283,8 @@ setKeepalivesCount(PGconn *conn)
char sebuf[256];
appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"),
+ libpq_gettext("setsockopt(%s) failed: %s\n"),
+ "TCP_KEEPCNT",
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
@@ -1777,7 +1774,8 @@ keep_going: /* We will come back to here until there is
(char *) &on, sizeof(on)) < 0)
{
appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"),
+ libpq_gettext("setsockopt(%s) failed: %s\n"),
+ "SO_KEEPALIVE",
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
err = 1;
}