Skip to content

Commit cba5b99

Browse files
committed
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
1 parent 50e570a commit cba5b99

File tree

4 files changed

+29
-31
lines changed

4 files changed

+29
-31
lines changed

doc/src/sgml/config.sgml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,9 +1012,9 @@ include_dir 'conf.d'
10121012
the kernel reports that the connection is closed.
10131013
</para>
10141014
<para>
1015-
This option is currently available only on systems that support the
1016-
non-standard <symbol>POLLRDHUP</symbol> extension to the
1017-
<symbol>poll</symbol> system call, including Linux.
1015+
This option relies on kernel events exposed by Linux, macOS, illumos
1016+
and the BSD family of operating systems, and is not currently available
1017+
on other systems.
10181018
</para>
10191019
<para>
10201020
If the value is specified without units, it is taken as milliseconds.

src/backend/libpq/pqcomm.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ pq_init(void)
204204
(errmsg("could not set socket to nonblocking mode: %m")));
205205
#endif
206206

207-
FeBeWaitSet = CreateWaitEventSet(TopMemoryContext, 3);
207+
FeBeWaitSet = CreateWaitEventSet(TopMemoryContext, FeBeWaitSetNEvents);
208208
socket_pos = AddWaitEventToSet(FeBeWaitSet, WL_SOCKET_WRITEABLE,
209209
MyProcPort->sock, NULL, NULL);
210210
latch_pos = AddWaitEventToSet(FeBeWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
@@ -1960,33 +1960,33 @@ pq_settcpusertimeout(int timeout, Port *port)
19601960
bool
19611961
pq_check_connection(void)
19621962
{
1963-
#if defined(POLLRDHUP)
1964-
/*
1965-
* POLLRDHUP is a Linux extension to poll(2) to detect sockets closed by
1966-
* the other end. We don't have a portable way to do that without
1967-
* actually trying to read or write data on other systems. We don't want
1968-
* to read because that would be confused by pipelined queries and COPY
1969-
* data. Perhaps in future we'll try to write a heartbeat message instead.
1970-
*/
1971-
struct pollfd pollfd;
1963+
WaitEvent events[FeBeWaitSetNEvents];
19721964
int rc;
19731965

1974-
pollfd.fd = MyProcPort->sock;
1975-
pollfd.events = POLLOUT | POLLIN | POLLRDHUP;
1976-
pollfd.revents = 0;
1977-
1978-
rc = poll(&pollfd, 1, 0);
1966+
/*
1967+
* It's OK to modify the socket event filter without restoring, because
1968+
* all FeBeWaitSet socket wait sites do the same.
1969+
*/
1970+
ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, WL_SOCKET_CLOSED, NULL);
19791971

1980-
if (rc < 0)
1972+
retry:
1973+
rc = WaitEventSetWait(FeBeWaitSet, 0, events, lengthof(events), 0);
1974+
for (int i = 0; i < rc; ++i)
19811975
{
1982-
ereport(COMMERROR,
1983-
(errcode_for_socket_access(),
1984-
errmsg("could not poll socket: %m")));
1985-
return false;
1976+
if (events[i].events & WL_SOCKET_CLOSED)
1977+
return false;
1978+
if (events[i].events & WL_LATCH_SET)
1979+
{
1980+
/*
1981+
* A latch event might be preventing other events from being
1982+
* reported. Reset it and poll again. No need to restore it
1983+
* because no code should expect latches to survive across
1984+
* CHECK_FOR_INTERRUPTS().
1985+
*/
1986+
ResetLatch(MyLatch);
1987+
goto retry;
1988+
}
19861989
}
1987-
else if (rc == 1 && (pollfd.revents & (POLLHUP | POLLRDHUP)))
1988-
return false;
1989-
#endif
19901990

19911991
return true;
19921992
}

src/backend/utils/misc/guc.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12192,14 +12192,11 @@ check_huge_page_size(int *newval, void **extra, GucSource source)
1219212192
static bool
1219312193
check_client_connection_check_interval(int *newval, void **extra, GucSource source)
1219412194
{
12195-
#ifndef POLLRDHUP
12196-
/* Linux only, for now. See pq_check_connection(). */
12197-
if (*newval != 0)
12195+
if (!WaitEventSetCanReportClosed() && *newval != 0)
1219812196
{
12199-
GUC_check_errdetail("client_connection_check_interval must be set to 0 on platforms that lack POLLRDHUP.");
12197+
GUC_check_errdetail("client_connection_check_interval must be set to 0 on this platform");
1220012198
return false;
1220112199
}
12202-
#endif
1220312200
return true;
1220412201
}
1220512202

src/include/libpq/libpq.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ extern WaitEventSet *FeBeWaitSet;
6262

6363
#define FeBeWaitSetSocketPos 0
6464
#define FeBeWaitSetLatchPos 1
65+
#define FeBeWaitSetNEvents 3
6566

6667
extern int StreamServerPort(int family, const char *hostName,
6768
unsigned short portNumber, const char *unixSocketDir,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy