Skip to content

Commit a180776

Browse files
committed
Teach unix_latch.c to use poll() where available.
poll() is preferred over select() on platforms where both are available, because it tends to be a bit faster and it doesn't have an arbitrary limit on the range of FD numbers that can be accessed. The FD range limit does not appear to be a risk factor for any 9.1 usages, so this doesn't need to be back-patched, but we need to have it in place if we keep on expanding the uses of WaitLatch.
1 parent d82d848 commit a180776

File tree

1 file changed

+98
-8
lines changed

1 file changed

+98
-8
lines changed

src/backend/port/unix_latch.c

Lines changed: 98 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
* however reliably interrupts the sleep, and causes select() to return
1515
* immediately even if the signal arrives before select() begins.
1616
*
17+
* (Actually, we prefer poll() over select() where available, but the
18+
* same comments apply to it.)
19+
*
1720
* When SetLatch is called from the same process that owns the latch,
1821
* SetLatch writes the byte directly to the pipe. If it's owned by another
1922
* process, SIGUSR1 is sent and the signal handler in the waiting process
@@ -34,6 +37,12 @@
3437
#include <unistd.h>
3538
#include <sys/time.h>
3639
#include <sys/types.h>
40+
#ifdef HAVE_POLL_H
41+
#include <poll.h>
42+
#endif
43+
#ifdef HAVE_SYS_POLL_H
44+
#include <sys/poll.h>
45+
#endif
3746
#ifdef HAVE_SYS_SELECT_H
3847
#include <sys/select.h>
3948
#endif
@@ -175,12 +184,18 @@ int
175184
WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
176185
long timeout)
177186
{
187+
int result = 0;
188+
int rc;
189+
#ifdef HAVE_POLL
190+
struct pollfd pfds[3];
191+
int nfds;
192+
#else
178193
struct timeval tv,
179194
*tvp = NULL;
180195
fd_set input_mask;
181196
fd_set output_mask;
182-
int rc;
183-
int result = 0;
197+
int hifd;
198+
#endif
184199

185200
/* Ignore WL_SOCKET_* events if no valid socket is given */
186201
if (sock == PGINVALID_SOCKET)
@@ -195,21 +210,29 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
195210
if (wakeEvents & WL_TIMEOUT)
196211
{
197212
Assert(timeout >= 0);
213+
#ifndef HAVE_POLL
198214
tv.tv_sec = timeout / 1000L;
199215
tv.tv_usec = (timeout % 1000L) * 1000L;
200216
tvp = &tv;
217+
#endif
218+
}
219+
else
220+
{
221+
#ifdef HAVE_POLL
222+
/* make sure poll() agrees there is no timeout */
223+
timeout = -1;
224+
#endif
201225
}
202226

203227
waiting = true;
204228
do
205229
{
206-
int hifd;
207-
208230
/*
209231
* Clear the pipe, then check if the latch is set already. If someone
210-
* sets the latch between this and the select() below, the setter will
211-
* write a byte to the pipe (or signal us and the signal handler will
212-
* do that), and the select() will return immediately.
232+
* sets the latch between this and the poll()/select() below, the
233+
* setter will write a byte to the pipe (or signal us and the signal
234+
* handler will do that), and the poll()/select() will return
235+
* immediately.
213236
*
214237
* Note: we assume that the kernel calls involved in drainSelfPipe()
215238
* and SetLatch() will provide adequate synchronization on machines
@@ -228,7 +251,73 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
228251
break;
229252
}
230253

231-
/* Must wait ... set up the event masks for select() */
254+
/* Must wait ... we use poll(2) if available, otherwise select(2) */
255+
#ifdef HAVE_POLL
256+
nfds = 0;
257+
if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
258+
{
259+
/* socket, if used, is always in pfds[0] */
260+
pfds[0].fd = sock;
261+
pfds[0].events = 0;
262+
if (wakeEvents & WL_SOCKET_READABLE)
263+
pfds[0].events |= POLLIN;
264+
if (wakeEvents & WL_SOCKET_WRITEABLE)
265+
pfds[0].events |= POLLOUT;
266+
pfds[0].revents = 0;
267+
nfds++;
268+
}
269+
270+
pfds[nfds].fd = selfpipe_readfd;
271+
pfds[nfds].events = POLLIN;
272+
pfds[nfds].revents = 0;
273+
nfds++;
274+
275+
if (wakeEvents & WL_POSTMASTER_DEATH)
276+
{
277+
/* postmaster fd, if used, is always in pfds[nfds - 1] */
278+
pfds[nfds].fd = postmaster_alive_fds[POSTMASTER_FD_WATCH];
279+
pfds[nfds].events = POLLIN;
280+
pfds[nfds].revents = 0;
281+
nfds++;
282+
}
283+
284+
/* Sleep */
285+
rc = poll(pfds, nfds, (int) timeout);
286+
287+
/* Check return code */
288+
if (rc < 0)
289+
{
290+
if (errno == EINTR)
291+
continue;
292+
waiting = false;
293+
ereport(ERROR,
294+
(errcode_for_socket_access(),
295+
errmsg("poll() failed: %m")));
296+
}
297+
if (rc == 0 && (wakeEvents & WL_TIMEOUT))
298+
{
299+
/* timeout exceeded */
300+
result |= WL_TIMEOUT;
301+
}
302+
if ((wakeEvents & WL_SOCKET_READABLE) &&
303+
(pfds[0].revents & POLLIN))
304+
{
305+
/* data available in socket */
306+
result |= WL_SOCKET_READABLE;
307+
}
308+
if ((wakeEvents & WL_SOCKET_WRITEABLE) &&
309+
(pfds[0].revents & POLLOUT))
310+
{
311+
result |= WL_SOCKET_WRITEABLE;
312+
}
313+
if ((wakeEvents & WL_POSTMASTER_DEATH) &&
314+
(pfds[nfds - 1].revents & POLLIN))
315+
{
316+
result |= WL_POSTMASTER_DEATH;
317+
}
318+
319+
#else /* !HAVE_POLL */
320+
232321
FD_ZERO(&input_mask);
233322
FD_ZERO(&output_mask);
234323

@@ -288,6 +377,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
288377
{
289378
result |= WL_POSTMASTER_DEATH;
290379
}
380+
#endif /* HAVE_POLL */
291381
} while (result == 0);
292382
waiting = false;
293383

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