Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)