0002-Use-WL_SOCKET_CLOSED-for-client_connection_check_int.patch
text/x-patch
Filename: 0002-Use-WL_SOCKET_CLOSED-for-client_connection_check_int.patch
Type: text/x-patch
Part: 1
Patch
Format: format-patch
Series: patch 0002
Subject: Use WL_SOCKET_CLOSED for client_connection_check_interval.
| File | + | − |
|---|---|---|
| src/backend/libpq/pqcomm.c | 13 | 22 |
| src/backend/utils/misc/guc.c | 1 | 16 |
From c29ca0d9262e7eacf900cb83f9fd0e655f4cc261 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 30 Apr 2021 10:48:32 +1200
Subject: [PATCH 2/2] Use WL_SOCKET_CLOSED for
client_connection_check_interval.
Previously we used poll() directly to check for a POLLRDHUP event.
Instead, use WaitEventSet to poll the socket for WL_SOCKET_CLOSED, which
knows how to detect that condition on more systems.
XXX Need to figure out a way to allow this feature only some builds,
but that information is currently private to latch.c
XXX May need to review the way eg POLLERR/POLLHUP and equivalents are
treated when you're waiting/polling for WL_SOCKET_CLOSED.
XXX Manually tested by killing psql, sending an async query with libpq
and then sending 'X' and hanging up, and by yanking an ethernet cable
(but the last requires TCP keepalives to be enabled). Need to find a
clever way to do at least the first two in a TAP (?) test without races.
---
src/backend/libpq/pqcomm.c | 35 +++++++++++++----------------------
src/backend/utils/misc/guc.c | 17 +----------------
2 files changed, 14 insertions(+), 38 deletions(-)
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index b9ccd4473f..1334dd4bb3 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1932,33 +1932,24 @@ pq_settcpusertimeout(int timeout, Port *port)
bool
pq_check_connection(void)
{
-#if defined(POLLRDHUP)
+ WaitEvent events[3];
+ int rc;
+
/*
- * POLLRDHUP is a Linux extension to poll(2) to detect sockets closed by
- * the other end. We don't have a portable way to do that without
- * actually trying to read or write data on other systems. We don't want
- * to read because that would be confused by pipelined queries and COPY
- * data. Perhaps in future we'll try to write a heartbeat message instead.
+ * Temporarily ignore the latch, while we check if the socket has been
+ * closed by the other end (if that is possible on this OS).
*/
- struct pollfd pollfd;
- int rc;
-
- pollfd.fd = MyProcPort->sock;
- pollfd.events = POLLOUT | POLLIN | POLLRDHUP;
- pollfd.revents = 0;
-
- rc = poll(&pollfd, 1, 0);
+ ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetLatchPos, WL_LATCH_SET, NULL);
+ ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, WL_SOCKET_CLOSED, NULL);
+ rc = WaitEventSetWait(FeBeWaitSet, 0, events, lengthof(events), 0);
+ ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetLatchPos, WL_LATCH_SET, MyLatch);
- if (rc < 0)
+ for (int i = 0; i < rc; ++i)
{
- ereport(COMMERROR,
- (errcode_for_socket_access(),
- errmsg("could not poll socket: %m")));
- return false;
+ if (events[i].pos == FeBeWaitSetSocketPos &&
+ events[i].events & WL_SOCKET_CLOSED)
+ return false;
}
- else if (rc == 1 && (pollfd.revents & (POLLHUP | POLLRDHUP)))
- return false;
-#endif
return true;
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index b130874bdc..60512ec82f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -209,7 +209,6 @@ static bool check_autovacuum_work_mem(int *newval, void **extra, GucSource sourc
static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
static bool check_maintenance_io_concurrency(int *newval, void **extra, GucSource source);
static bool check_huge_page_size(int *newval, void **extra, GucSource source);
-static bool check_client_connection_check_interval(int *newval, void **extra, GucSource source);
static void assign_maintenance_io_concurrency(int newval, void *extra);
static void assign_pgstat_temp_directory(const char *newval, void *extra);
static bool check_application_name(char **newval, void **extra, GucSource source);
@@ -3580,7 +3579,7 @@ static struct config_int ConfigureNamesInt[] =
},
&client_connection_check_interval,
0, 0, INT_MAX,
- check_client_connection_check_interval, NULL, NULL
+ NULL, NULL, NULL
},
/* End-of-list marker */
@@ -12094,20 +12093,6 @@ check_huge_page_size(int *newval, void **extra, GucSource source)
return true;
}
-static bool
-check_client_connection_check_interval(int *newval, void **extra, GucSource source)
-{
-#ifndef POLLRDHUP
- /* Linux only, for now. See pq_check_connection(). */
- if (*newval != 0)
- {
- GUC_check_errdetail("client_connection_check_interval must be set to 0 on platforms that lack POLLRDHUP.");
- return false;
- }
-#endif
- return true;
-}
-
static void
assign_maintenance_io_concurrency(int newval, void *extra)
{
--
2.30.2