valgrind: do leak checking, and exit with code 1 on error (not 0)
[gnulib/ericb.git] / lib / poll.c
blob8ce68c01548c76749f519dbacf96c1a433cc24aa
1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22 /* Tell gcc not to warn about the (nfd < 0) tests, below. */
23 #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
24 # pragma GCC diagnostic ignored "-Wtype-limits"
25 #endif
27 #include <config.h>
28 #include <alloca.h>
30 #include <sys/types.h>
32 /* Specification. */
33 #include <poll.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <assert.h>
39 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
40 # define WIN32_NATIVE
41 # include <winsock2.h>
42 # include <windows.h>
43 # include <io.h>
44 # include <stdio.h>
45 # include <conio.h>
46 #else
47 # include <sys/time.h>
48 # include <sys/socket.h>
49 # include <sys/select.h>
50 # include <unistd.h>
51 #endif
53 #ifdef HAVE_SYS_IOCTL_H
54 # include <sys/ioctl.h>
55 #endif
56 #ifdef HAVE_SYS_FILIO_H
57 # include <sys/filio.h>
58 #endif
60 #include <time.h>
62 #ifndef INFTIM
63 # define INFTIM (-1)
64 #endif
66 /* BeOS does not have MSG_PEEK. */
67 #ifndef MSG_PEEK
68 # define MSG_PEEK 0
69 #endif
71 #ifdef WIN32_NATIVE
73 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
75 static BOOL
76 IsSocketHandle (HANDLE h)
78 WSANETWORKEVENTS ev;
80 if (IsConsoleHandle (h))
81 return FALSE;
83 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
84 WSAEnumNetworkEvents instead distinguishes the two correctly. */
85 ev.lNetworkEvents = 0xDEADBEEF;
86 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
87 return ev.lNetworkEvents != 0xDEADBEEF;
90 /* Declare data structures for ntdll functions. */
91 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
92 ULONG NamedPipeType;
93 ULONG NamedPipeConfiguration;
94 ULONG MaximumInstances;
95 ULONG CurrentInstances;
96 ULONG InboundQuota;
97 ULONG ReadDataAvailable;
98 ULONG OutboundQuota;
99 ULONG WriteQuotaAvailable;
100 ULONG NamedPipeState;
101 ULONG NamedPipeEnd;
102 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
104 typedef struct _IO_STATUS_BLOCK
106 union {
107 DWORD Status;
108 PVOID Pointer;
109 } u;
110 ULONG_PTR Information;
111 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
113 typedef enum _FILE_INFORMATION_CLASS {
114 FilePipeLocalInformation = 24
115 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
117 typedef DWORD (WINAPI *PNtQueryInformationFile)
118 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
120 # ifndef PIPE_BUF
121 # define PIPE_BUF 512
122 # endif
124 /* Compute revents values for file handle H. If some events cannot happen
125 for the handle, eliminate them from *P_SOUGHT. */
127 static int
128 win32_compute_revents (HANDLE h, int *p_sought)
130 int i, ret, happened;
131 INPUT_RECORD *irbuffer;
132 DWORD avail, nbuffer;
133 BOOL bRet;
134 IO_STATUS_BLOCK iosb;
135 FILE_PIPE_LOCAL_INFORMATION fpli;
136 static PNtQueryInformationFile NtQueryInformationFile;
137 static BOOL once_only;
139 switch (GetFileType (h))
141 case FILE_TYPE_PIPE:
142 if (!once_only)
144 NtQueryInformationFile = (PNtQueryInformationFile)
145 GetProcAddress (GetModuleHandle ("ntdll.dll"),
146 "NtQueryInformationFile");
147 once_only = TRUE;
150 happened = 0;
151 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
153 if (avail)
154 happened |= *p_sought & (POLLIN | POLLRDNORM);
156 else if (GetLastError () == ERROR_BROKEN_PIPE)
157 happened |= POLLHUP;
159 else
161 /* It was the write-end of the pipe. Check if it is writable.
162 If NtQueryInformationFile fails, optimistically assume the pipe is
163 writable. This could happen on Win9x, where NtQueryInformationFile
164 is not available, or if we inherit a pipe that doesn't permit
165 FILE_READ_ATTRIBUTES access on the write end (I think this should
166 not happen since WinXP SP2; WINE seems fine too). Otherwise,
167 ensure that enough space is available for atomic writes. */
168 memset (&iosb, 0, sizeof (iosb));
169 memset (&fpli, 0, sizeof (fpli));
171 if (!NtQueryInformationFile
172 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
173 FilePipeLocalInformation)
174 || fpli.WriteQuotaAvailable >= PIPE_BUF
175 || (fpli.OutboundQuota < PIPE_BUF &&
176 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
177 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
179 return happened;
181 case FILE_TYPE_CHAR:
182 ret = WaitForSingleObject (h, 0);
183 if (!IsConsoleHandle (h))
184 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
186 nbuffer = avail = 0;
187 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
188 if (bRet)
190 /* Input buffer. */
191 *p_sought &= POLLIN | POLLRDNORM;
192 if (nbuffer == 0)
193 return POLLHUP;
194 if (!*p_sought)
195 return 0;
197 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
198 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
199 if (!bRet || avail == 0)
200 return POLLHUP;
202 for (i = 0; i < avail; i++)
203 if (irbuffer[i].EventType == KEY_EVENT)
204 return *p_sought;
205 return 0;
207 else
209 /* Screen buffer. */
210 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
211 return *p_sought;
214 default:
215 ret = WaitForSingleObject (h, 0);
216 if (ret == WAIT_OBJECT_0)
217 return *p_sought & ~(POLLPRI | POLLRDBAND);
219 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
223 /* Convert fd_sets returned by select into revents values. */
225 static int
226 win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
228 int happened = 0;
230 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
231 happened |= (POLLIN | POLLRDNORM) & sought;
233 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
235 int r, error;
237 char data[64];
238 WSASetLastError (0);
239 r = recv (h, data, sizeof (data), MSG_PEEK);
240 error = WSAGetLastError ();
241 WSASetLastError (0);
243 if (r > 0 || error == WSAENOTCONN)
244 happened |= (POLLIN | POLLRDNORM) & sought;
246 /* Distinguish hung-up sockets from other errors. */
247 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
248 || error == WSAECONNABORTED || error == WSAENETRESET)
249 happened |= POLLHUP;
251 else
252 happened |= POLLERR;
255 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
256 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
258 if (lNetworkEvents & FD_OOB)
259 happened |= (POLLPRI | POLLRDBAND) & sought;
261 return happened;
264 #else /* !MinGW */
266 /* Convert select(2) returned fd_sets into poll(2) revents values. */
267 static int
268 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
270 int happened = 0;
271 if (FD_ISSET (fd, rfds))
273 int r;
274 int socket_errno;
276 # if defined __MACH__ && defined __APPLE__
277 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
278 for some kinds of descriptors. Detect if this descriptor is a
279 connected socket, a server socket, or something else using a
280 0-byte recv, and use ioctl(2) to detect POLLHUP. */
281 r = recv (fd, NULL, 0, MSG_PEEK);
282 socket_errno = (r < 0) ? errno : 0;
283 if (r == 0 || socket_errno == ENOTSOCK)
284 ioctl (fd, FIONREAD, &r);
285 # else
286 char data[64];
287 r = recv (fd, data, sizeof (data), MSG_PEEK);
288 socket_errno = (r < 0) ? errno : 0;
289 # endif
290 if (r == 0)
291 happened |= POLLHUP;
293 /* If the event happened on an unconnected server socket,
294 that's fine. */
295 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
296 happened |= (POLLIN | POLLRDNORM) & sought;
298 /* Distinguish hung-up sockets from other errors. */
299 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
300 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
301 happened |= POLLHUP;
303 else
304 happened |= POLLERR;
307 if (FD_ISSET (fd, wfds))
308 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
310 if (FD_ISSET (fd, efds))
311 happened |= (POLLPRI | POLLRDBAND) & sought;
313 return happened;
315 #endif /* !MinGW */
318 poll (struct pollfd *pfd, nfds_t nfd, int timeout)
320 #ifndef WIN32_NATIVE
321 fd_set rfds, wfds, efds;
322 struct timeval tv;
323 struct timeval *ptv;
324 int maxfd, rc;
325 nfds_t i;
327 # ifdef _SC_OPEN_MAX
328 static int sc_open_max = -1;
330 if (nfd < 0
331 || (nfd > sc_open_max
332 && (sc_open_max != -1
333 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
335 errno = EINVAL;
336 return -1;
338 # else /* !_SC_OPEN_MAX */
339 # ifdef OPEN_MAX
340 if (nfd < 0 || nfd > OPEN_MAX)
342 errno = EINVAL;
343 return -1;
345 # endif /* OPEN_MAX -- else, no check is needed */
346 # endif /* !_SC_OPEN_MAX */
348 /* EFAULT is not necessary to implement, but let's do it in the
349 simplest case. */
350 if (!pfd)
352 errno = EFAULT;
353 return -1;
356 /* convert timeout number into a timeval structure */
357 if (timeout == 0)
359 ptv = &tv;
360 ptv->tv_sec = 0;
361 ptv->tv_usec = 0;
363 else if (timeout > 0)
365 ptv = &tv;
366 ptv->tv_sec = timeout / 1000;
367 ptv->tv_usec = (timeout % 1000) * 1000;
369 else if (timeout == INFTIM)
370 /* wait forever */
371 ptv = NULL;
372 else
374 errno = EINVAL;
375 return -1;
378 /* create fd sets and determine max fd */
379 maxfd = -1;
380 FD_ZERO (&rfds);
381 FD_ZERO (&wfds);
382 FD_ZERO (&efds);
383 for (i = 0; i < nfd; i++)
385 if (pfd[i].fd < 0)
386 continue;
388 if (pfd[i].events & (POLLIN | POLLRDNORM))
389 FD_SET (pfd[i].fd, &rfds);
391 /* see select(2): "the only exceptional condition detectable
392 is out-of-band data received on a socket", hence we push
393 POLLWRBAND events onto wfds instead of efds. */
394 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
395 FD_SET (pfd[i].fd, &wfds);
396 if (pfd[i].events & (POLLPRI | POLLRDBAND))
397 FD_SET (pfd[i].fd, &efds);
398 if (pfd[i].fd >= maxfd
399 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
400 | POLLRDNORM | POLLRDBAND
401 | POLLWRNORM | POLLWRBAND)))
403 maxfd = pfd[i].fd;
404 if (maxfd > FD_SETSIZE)
406 errno = EOVERFLOW;
407 return -1;
412 /* examine fd sets */
413 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
414 if (rc < 0)
415 return rc;
417 /* establish results */
418 rc = 0;
419 for (i = 0; i < nfd; i++)
420 if (pfd[i].fd < 0)
421 pfd[i].revents = 0;
422 else
424 int happened = compute_revents (pfd[i].fd, pfd[i].events,
425 &rfds, &wfds, &efds);
426 if (happened)
428 pfd[i].revents = happened;
429 rc++;
433 return rc;
434 #else
435 static struct timeval tv0;
436 static HANDLE hEvent;
437 WSANETWORKEVENTS ev;
438 HANDLE h, handle_array[FD_SETSIZE + 2];
439 DWORD ret, wait_timeout, nhandles;
440 fd_set rfds, wfds, xfds;
441 BOOL poll_again;
442 MSG msg;
443 int rc = 0;
444 nfds_t i;
446 if (nfd < 0 || timeout < -1)
448 errno = EINVAL;
449 return -1;
452 if (!hEvent)
453 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
455 handle_array[0] = hEvent;
456 nhandles = 1;
457 FD_ZERO (&rfds);
458 FD_ZERO (&wfds);
459 FD_ZERO (&xfds);
461 /* Classify socket handles and create fd sets. */
462 for (i = 0; i < nfd; i++)
464 int sought = pfd[i].events;
465 pfd[i].revents = 0;
466 if (pfd[i].fd < 0)
467 continue;
468 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
469 | POLLPRI | POLLRDBAND)))
470 continue;
472 h = (HANDLE) _get_osfhandle (pfd[i].fd);
473 assert (h != NULL);
474 if (IsSocketHandle (h))
476 int requested = FD_CLOSE;
478 /* see above; socket handles are mapped onto select. */
479 if (sought & (POLLIN | POLLRDNORM))
481 requested |= FD_READ | FD_ACCEPT;
482 FD_SET ((SOCKET) h, &rfds);
484 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
486 requested |= FD_WRITE | FD_CONNECT;
487 FD_SET ((SOCKET) h, &wfds);
489 if (sought & (POLLPRI | POLLRDBAND))
491 requested |= FD_OOB;
492 FD_SET ((SOCKET) h, &xfds);
495 if (requested)
496 WSAEventSelect ((SOCKET) h, hEvent, requested);
498 else
500 /* Poll now. If we get an event, do not poll again. Also,
501 screen buffer handles are waitable, and they'll block until
502 a character is available. win32_compute_revents eliminates
503 bits for the "wrong" direction. */
504 pfd[i].revents = win32_compute_revents (h, &sought);
505 if (sought)
506 handle_array[nhandles++] = h;
507 if (pfd[i].revents)
508 timeout = 0;
512 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
514 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
515 no need to call select again. */
516 poll_again = FALSE;
517 wait_timeout = 0;
519 else
521 poll_again = TRUE;
522 if (timeout == INFTIM)
523 wait_timeout = INFINITE;
524 else
525 wait_timeout = timeout;
528 for (;;)
530 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
531 wait_timeout, QS_ALLINPUT);
533 if (ret == WAIT_OBJECT_0 + nhandles)
535 /* new input of some other kind */
536 BOOL bRet;
537 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
539 TranslateMessage (&msg);
540 DispatchMessage (&msg);
543 else
544 break;
547 if (poll_again)
548 select (0, &rfds, &wfds, &xfds, &tv0);
550 /* Place a sentinel at the end of the array. */
551 handle_array[nhandles] = NULL;
552 nhandles = 1;
553 for (i = 0; i < nfd; i++)
555 int happened;
557 if (pfd[i].fd < 0)
558 continue;
559 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
560 POLLOUT | POLLWRNORM | POLLWRBAND)))
561 continue;
563 h = (HANDLE) _get_osfhandle (pfd[i].fd);
564 if (h != handle_array[nhandles])
566 /* It's a socket. */
567 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
568 WSAEventSelect ((SOCKET) h, 0, 0);
570 /* If we're lucky, WSAEnumNetworkEvents already provided a way
571 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
572 if (FD_ISSET ((SOCKET) h, &rfds)
573 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
574 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
575 if (FD_ISSET ((SOCKET) h, &wfds))
576 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
577 if (FD_ISSET ((SOCKET) h, &xfds))
578 ev.lNetworkEvents |= FD_OOB;
580 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
581 ev.lNetworkEvents);
583 else
585 /* Not a socket. */
586 int sought = pfd[i].events;
587 happened = win32_compute_revents (h, &sought);
588 nhandles++;
591 if ((pfd[i].revents |= happened) != 0)
592 rc++;
595 return rc;
596 #endif