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