diff options
author | Thomas Munro <tmunro@postgresql.org> | 2022-02-14 16:29:44 +1300 |
---|---|---|
committer | Thomas Munro <tmunro@postgresql.org> | 2022-02-14 16:52:23 +1300 |
commit | cba5b994c990bba8df9b8bb75f25ca40aef6b68b (patch) | |
tree | 8189f1b0691ee24a9289afceb3dbf2ea1a4bcd6d /src/backend/libpq/pqcomm.c | |
parent | 50e570a59e7f86bb41f029a66b781fc79b8d50f1 (diff) | |
download | postgresql-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.c | 46 |
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; } |