aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqcomm.c
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2022-02-14 16:29:44 +1300
committerThomas Munro <tmunro@postgresql.org>2022-02-14 16:52:23 +1300
commitcba5b994c990bba8df9b8bb75f25ca40aef6b68b (patch)
tree8189f1b0691ee24a9289afceb3dbf2ea1a4bcd6d /src/backend/libpq/pqcomm.c
parent50e570a59e7f86bb41f029a66b781fc79b8d50f1 (diff)
downloadpostgresql-cba5b994c990bba8df9b8bb75f25ca40aef6b68b.tar.gz
postgresql-cba5b994c990bba8df9b8bb75f25ca40aef6b68b.zip
Use WL_SOCKET_CLOSED for client_connection_check_interval.
Previously we used poll() directly to check for a POLLRDHUP event. Instead, use the WaitEventSet API to poll the socket for WL_SOCKET_CLOSED, which knows how to detect this condition on many more operating systems. Reviewed-by: Zhihong Yu <zyu@yugabyte.com> Reviewed-by: Maksim Milyutin <milyutinma@gmail.com> Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/77def86b27e41f0efcba411460e929ae%40postgrespro.ru
Diffstat (limited to 'src/backend/libpq/pqcomm.c')
-rw-r--r--src/backend/libpq/pqcomm.c46
1 files changed, 23 insertions, 23 deletions
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 22eb04948ec..9e34f616deb 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -204,7 +204,7 @@ pq_init(void)
(errmsg("could not set socket to nonblocking mode: %m")));
#endif
- FeBeWaitSet = CreateWaitEventSet(TopMemoryContext, 3);
+ FeBeWaitSet = CreateWaitEventSet(TopMemoryContext, FeBeWaitSetNEvents);
socket_pos = AddWaitEventToSet(FeBeWaitSet, WL_SOCKET_WRITEABLE,
MyProcPort->sock, NULL, NULL);
latch_pos = AddWaitEventToSet(FeBeWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
@@ -1960,33 +1960,33 @@ pq_settcpusertimeout(int timeout, Port *port)
bool
pq_check_connection(void)
{
-#if defined(POLLRDHUP)
- /*
- * 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.
- */
- struct pollfd pollfd;
+ WaitEvent events[FeBeWaitSetNEvents];
int rc;
- pollfd.fd = MyProcPort->sock;
- pollfd.events = POLLOUT | POLLIN | POLLRDHUP;
- pollfd.revents = 0;
-
- rc = poll(&pollfd, 1, 0);
+ /*
+ * It's OK to modify the socket event filter without restoring, because
+ * all FeBeWaitSet socket wait sites do the same.
+ */
+ ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, WL_SOCKET_CLOSED, NULL);
- if (rc < 0)
+retry:
+ rc = WaitEventSetWait(FeBeWaitSet, 0, events, lengthof(events), 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].events & WL_SOCKET_CLOSED)
+ return false;
+ if (events[i].events & WL_LATCH_SET)
+ {
+ /*
+ * A latch event might be preventing other events from being
+ * reported. Reset it and poll again. No need to restore it
+ * because no code should expect latches to survive across
+ * CHECK_FOR_INTERRUPTS().
+ */
+ ResetLatch(MyLatch);
+ goto retry;
+ }
}
- else if (rc == 1 && (pollfd.revents & (POLLHUP | POLLRDHUP)))
- return false;
-#endif
return true;
}