autoupdate
[gnulib.git] / lib / poll.c
blobda3d8911b70f9f0e3d03ab955ed34ecfda27fc6c
1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2018 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, see <https://www.gnu.org/licenses/>. */
21 /* Tell gcc not to warn about the (nfd < 0) tests, below. */
22 #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
23 # pragma GCC diagnostic ignored "-Wtype-limits"
24 #endif
26 #include <config.h>
27 #include <alloca.h>
29 #include <sys/types.h>
31 /* Specification. */
32 #include <poll.h>
34 #include <errno.h>
35 #include <limits.h>
37 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
38 # define WINDOWS_NATIVE
39 # include <winsock2.h>
40 # include <windows.h>
41 # include <io.h>
42 # include <stdio.h>
43 # include <conio.h>
44 # if GNULIB_MSVC_NOTHROW
45 # include "msvc-nothrow.h"
46 # else
47 # include <io.h>
48 # endif
49 #else
50 # include <sys/time.h>
51 # include <unistd.h>
52 #endif
54 #include <sys/select.h>
55 #include <sys/socket.h>
57 #ifdef HAVE_SYS_IOCTL_H
58 # include <sys/ioctl.h>
59 #endif
60 #ifdef HAVE_SYS_FILIO_H
61 # include <sys/filio.h>
62 #endif
64 #include <time.h>
66 #include "assure.h"
68 #ifndef INFTIM
69 # define INFTIM (-1)
70 #endif
72 /* BeOS does not have MSG_PEEK. */
73 #ifndef MSG_PEEK
74 # define MSG_PEEK 0
75 #endif
77 #ifdef WINDOWS_NATIVE
79 /* Here we need the recv() function from Windows, that takes a SOCKET as
80 first argument, not any possible gnulib override. */
81 # undef recv
83 /* Here we need the select() function from Windows, because we pass bit masks
84 of SOCKETs, not bit masks of FDs. */
85 # undef select
87 static BOOL IsConsoleHandle (HANDLE h)
89 DWORD mode;
90 return GetConsoleMode (h, &mode) != 0;
93 static BOOL
94 IsSocketHandle (HANDLE h)
96 WSANETWORKEVENTS ev;
98 if (IsConsoleHandle (h))
99 return FALSE;
101 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
102 WSAEnumNetworkEvents instead distinguishes the two correctly. */
103 ev.lNetworkEvents = 0xDEADBEEF;
104 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
105 return ev.lNetworkEvents != 0xDEADBEEF;
108 /* Declare data structures for ntdll functions. */
109 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
110 ULONG NamedPipeType;
111 ULONG NamedPipeConfiguration;
112 ULONG MaximumInstances;
113 ULONG CurrentInstances;
114 ULONG InboundQuota;
115 ULONG ReadDataAvailable;
116 ULONG OutboundQuota;
117 ULONG WriteQuotaAvailable;
118 ULONG NamedPipeState;
119 ULONG NamedPipeEnd;
120 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
122 typedef struct _IO_STATUS_BLOCK
124 union {
125 DWORD Status;
126 PVOID Pointer;
127 } u;
128 ULONG_PTR Information;
129 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
131 typedef enum _FILE_INFORMATION_CLASS {
132 FilePipeLocalInformation = 24
133 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
135 typedef DWORD (WINAPI *PNtQueryInformationFile)
136 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
138 # ifndef PIPE_BUF
139 # define PIPE_BUF 512
140 # endif
142 /* Compute revents values for file handle H. If some events cannot happen
143 for the handle, eliminate them from *P_SOUGHT. */
145 static int
146 windows_compute_revents (HANDLE h, int *p_sought)
148 int i, ret, happened;
149 INPUT_RECORD *irbuffer;
150 DWORD avail, nbuffer;
151 BOOL bRet;
152 IO_STATUS_BLOCK iosb;
153 FILE_PIPE_LOCAL_INFORMATION fpli;
154 static PNtQueryInformationFile NtQueryInformationFile;
155 static BOOL once_only;
157 switch (GetFileType (h))
159 case FILE_TYPE_PIPE:
160 if (!once_only)
162 NtQueryInformationFile = (PNtQueryInformationFile)
163 GetProcAddress (GetModuleHandle ("ntdll.dll"),
164 "NtQueryInformationFile");
165 once_only = TRUE;
168 happened = 0;
169 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
171 if (avail)
172 happened |= *p_sought & (POLLIN | POLLRDNORM);
174 else if (GetLastError () == ERROR_BROKEN_PIPE)
175 happened |= POLLHUP;
177 else
179 /* It was the write-end of the pipe. Check if it is writable.
180 If NtQueryInformationFile fails, optimistically assume the pipe is
181 writable. This could happen on Windows 9x, where
182 NtQueryInformationFile is not available, or if we inherit a pipe
183 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
184 (I think this should not happen since Windows XP SP2; WINE seems
185 fine too). Otherwise, ensure that enough space is available for
186 atomic writes. */
187 memset (&iosb, 0, sizeof (iosb));
188 memset (&fpli, 0, sizeof (fpli));
190 if (!NtQueryInformationFile
191 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
192 FilePipeLocalInformation)
193 || fpli.WriteQuotaAvailable >= PIPE_BUF
194 || (fpli.OutboundQuota < PIPE_BUF &&
195 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
196 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
198 return happened;
200 case FILE_TYPE_CHAR:
201 ret = WaitForSingleObject (h, 0);
202 if (!IsConsoleHandle (h))
203 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
205 nbuffer = avail = 0;
206 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
207 if (bRet)
209 /* Input buffer. */
210 *p_sought &= POLLIN | POLLRDNORM;
211 if (nbuffer == 0)
212 return POLLHUP;
213 if (!*p_sought)
214 return 0;
216 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
217 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
218 if (!bRet || avail == 0)
219 return POLLHUP;
221 for (i = 0; i < avail; i++)
222 if (irbuffer[i].EventType == KEY_EVENT)
223 return *p_sought;
224 return 0;
226 else
228 /* Screen buffer. */
229 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
230 return *p_sought;
233 default:
234 ret = WaitForSingleObject (h, 0);
235 if (ret == WAIT_OBJECT_0)
236 return *p_sought & ~(POLLPRI | POLLRDBAND);
238 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
242 /* Convert fd_sets returned by select into revents values. */
244 static int
245 windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
247 int happened = 0;
249 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
250 happened |= (POLLIN | POLLRDNORM) & sought;
252 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
254 int r, error;
256 char data[64];
257 WSASetLastError (0);
258 r = recv (h, data, sizeof (data), MSG_PEEK);
259 error = WSAGetLastError ();
260 WSASetLastError (0);
262 if (r > 0 || error == WSAENOTCONN)
263 happened |= (POLLIN | POLLRDNORM) & sought;
265 /* Distinguish hung-up sockets from other errors. */
266 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
267 || error == WSAECONNABORTED || error == WSAENETRESET)
268 happened |= POLLHUP;
270 else
271 happened |= POLLERR;
274 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
275 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
277 if (lNetworkEvents & FD_OOB)
278 happened |= (POLLPRI | POLLRDBAND) & sought;
280 return happened;
283 #else /* !MinGW */
285 /* Convert select(2) returned fd_sets into poll(2) revents values. */
286 static int
287 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
289 int happened = 0;
290 if (FD_ISSET (fd, rfds))
292 int r;
293 int socket_errno;
295 # if defined __MACH__ && defined __APPLE__
296 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
297 for some kinds of descriptors. Detect if this descriptor is a
298 connected socket, a server socket, or something else using a
299 0-byte recv, and use ioctl(2) to detect POLLHUP. */
300 r = recv (fd, NULL, 0, MSG_PEEK);
301 socket_errno = (r < 0) ? errno : 0;
302 if (r == 0 || socket_errno == ENOTSOCK)
303 ioctl (fd, FIONREAD, &r);
304 # else
305 char data[64];
306 r = recv (fd, data, sizeof (data), MSG_PEEK);
307 socket_errno = (r < 0) ? errno : 0;
308 # endif
309 if (r == 0)
310 happened |= POLLHUP;
312 /* If the event happened on an unconnected server socket,
313 that's fine. */
314 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
315 happened |= (POLLIN | POLLRDNORM) & sought;
317 /* Distinguish hung-up sockets from other errors. */
318 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
319 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
320 happened |= POLLHUP;
322 /* some systems can't use recv() on non-socket, including HP NonStop */
323 else if (socket_errno == ENOTSOCK)
324 happened |= (POLLIN | POLLRDNORM) & sought;
326 else
327 happened |= POLLERR;
330 if (FD_ISSET (fd, wfds))
331 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
333 if (FD_ISSET (fd, efds))
334 happened |= (POLLPRI | POLLRDBAND) & sought;
336 return happened;
338 #endif /* !MinGW */
341 poll (struct pollfd *pfd, nfds_t nfd, int timeout)
343 #ifndef WINDOWS_NATIVE
344 fd_set rfds, wfds, efds;
345 struct timeval tv;
346 struct timeval *ptv;
347 int maxfd, rc;
348 nfds_t i;
350 if (nfd > INT_MAX)
352 errno = EINVAL;
353 return -1;
355 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
356 of a too-large NFD is caught by one of the other checks below, and
357 checking directly for getdtablesize is too much of a portability
358 and/or performance and/or correctness hassle. */
360 /* EFAULT is not necessary to implement, but let's do it in the
361 simplest case. */
362 if (!pfd && nfd)
364 errno = EFAULT;
365 return -1;
368 /* convert timeout number into a timeval structure */
369 if (timeout == 0)
371 ptv = &tv;
372 ptv->tv_sec = 0;
373 ptv->tv_usec = 0;
375 else if (timeout > 0)
377 ptv = &tv;
378 ptv->tv_sec = timeout / 1000;
379 ptv->tv_usec = (timeout % 1000) * 1000;
381 else if (timeout == INFTIM)
382 /* wait forever */
383 ptv = NULL;
384 else
386 errno = EINVAL;
387 return -1;
390 /* create fd sets and determine max fd */
391 maxfd = -1;
392 FD_ZERO (&rfds);
393 FD_ZERO (&wfds);
394 FD_ZERO (&efds);
395 for (i = 0; i < nfd; i++)
397 if (pfd[i].fd < 0)
398 continue;
399 if (maxfd < pfd[i].fd)
401 maxfd = pfd[i].fd;
402 if (FD_SETSIZE <= maxfd)
404 errno = EINVAL;
405 return -1;
408 if (pfd[i].events & (POLLIN | POLLRDNORM))
409 FD_SET (pfd[i].fd, &rfds);
410 /* see select(2): "the only exceptional condition detectable
411 is out-of-band data received on a socket", hence we push
412 POLLWRBAND events onto wfds instead of efds. */
413 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
414 FD_SET (pfd[i].fd, &wfds);
415 if (pfd[i].events & (POLLPRI | POLLRDBAND))
416 FD_SET (pfd[i].fd, &efds);
419 /* examine fd sets */
420 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
421 if (rc < 0)
422 return rc;
424 /* establish results */
425 rc = 0;
426 for (i = 0; i < nfd; i++)
428 pfd[i].revents = (pfd[i].fd < 0
430 : compute_revents (pfd[i].fd, pfd[i].events,
431 &rfds, &wfds, &efds));
432 rc += pfd[i].revents != 0;
435 return rc;
436 #else
437 static struct timeval tv0;
438 static HANDLE hEvent;
439 WSANETWORKEVENTS ev;
440 HANDLE h, handle_array[FD_SETSIZE + 2];
441 DWORD ret, wait_timeout, nhandles;
442 fd_set rfds, wfds, xfds;
443 BOOL poll_again;
444 MSG msg;
445 int rc = 0;
446 nfds_t i;
448 if (nfd > INT_MAX || timeout < -1)
450 errno = EINVAL;
451 return -1;
454 if (!hEvent)
455 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
457 restart:
458 handle_array[0] = hEvent;
459 nhandles = 1;
460 FD_ZERO (&rfds);
461 FD_ZERO (&wfds);
462 FD_ZERO (&xfds);
464 /* Classify socket handles and create fd sets. */
465 for (i = 0; i < nfd; i++)
467 int sought = pfd[i].events;
468 pfd[i].revents = 0;
469 if (pfd[i].fd < 0)
470 continue;
471 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
472 | POLLPRI | POLLRDBAND)))
473 continue;
475 h = (HANDLE) _get_osfhandle (pfd[i].fd);
476 assure (h != NULL);
477 if (IsSocketHandle (h))
479 int requested = FD_CLOSE;
481 /* see above; socket handles are mapped onto select. */
482 if (sought & (POLLIN | POLLRDNORM))
484 requested |= FD_READ | FD_ACCEPT;
485 FD_SET ((SOCKET) h, &rfds);
487 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
489 requested |= FD_WRITE | FD_CONNECT;
490 FD_SET ((SOCKET) h, &wfds);
492 if (sought & (POLLPRI | POLLRDBAND))
494 requested |= FD_OOB;
495 FD_SET ((SOCKET) h, &xfds);
498 if (requested)
499 WSAEventSelect ((SOCKET) h, hEvent, requested);
501 else
503 /* Poll now. If we get an event, do not poll again. Also,
504 screen buffer handles are waitable, and they'll block until
505 a character is available. windows_compute_revents eliminates
506 bits for the "wrong" direction. */
507 pfd[i].revents = windows_compute_revents (h, &sought);
508 if (sought)
509 handle_array[nhandles++] = h;
510 if (pfd[i].revents)
511 timeout = 0;
515 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
517 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
518 no need to call select again. */
519 poll_again = FALSE;
520 wait_timeout = 0;
522 else
524 poll_again = TRUE;
525 if (timeout == INFTIM)
526 wait_timeout = INFINITE;
527 else
528 wait_timeout = timeout;
531 for (;;)
533 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
534 wait_timeout, QS_ALLINPUT);
536 if (ret == WAIT_OBJECT_0 + nhandles)
538 /* new input of some other kind */
539 BOOL bRet;
540 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
542 TranslateMessage (&msg);
543 DispatchMessage (&msg);
546 else
547 break;
550 if (poll_again)
551 select (0, &rfds, &wfds, &xfds, &tv0);
553 /* Place a sentinel at the end of the array. */
554 handle_array[nhandles] = NULL;
555 nhandles = 1;
556 for (i = 0; i < nfd; i++)
558 int happened;
560 if (pfd[i].fd < 0)
561 continue;
562 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
563 POLLOUT | POLLWRNORM | POLLWRBAND)))
564 continue;
566 h = (HANDLE) _get_osfhandle (pfd[i].fd);
567 if (h != handle_array[nhandles])
569 /* It's a socket. */
570 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
571 WSAEventSelect ((SOCKET) h, 0, 0);
573 /* If we're lucky, WSAEnumNetworkEvents already provided a way
574 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
575 if (FD_ISSET ((SOCKET) h, &rfds)
576 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
577 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
578 if (FD_ISSET ((SOCKET) h, &wfds))
579 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
580 if (FD_ISSET ((SOCKET) h, &xfds))
581 ev.lNetworkEvents |= FD_OOB;
583 happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
584 ev.lNetworkEvents);
586 else
588 /* Not a socket. */
589 int sought = pfd[i].events;
590 happened = windows_compute_revents (h, &sought);
591 nhandles++;
594 if ((pfd[i].revents |= happened) != 0)
595 rc++;
598 if (!rc && timeout == INFTIM)
600 SleepEx (1, TRUE);
601 goto restart;
604 return rc;
605 #endif