mountlist: Use Linux code on Android.
[gnulib.git] / lib / poll.c
blobf6de24c7938bc85b7d6c8f65aebd5419f461280c
1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2019 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 __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 /* Avoid warnings from gcc -Wcast-function-type. */
88 # define GetProcAddress \
89 (void *) GetProcAddress
91 static BOOL IsConsoleHandle (HANDLE h)
93 DWORD mode;
94 return GetConsoleMode (h, &mode) != 0;
97 static BOOL
98 IsSocketHandle (HANDLE h)
100 WSANETWORKEVENTS ev;
102 if (IsConsoleHandle (h))
103 return FALSE;
105 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
106 WSAEnumNetworkEvents instead distinguishes the two correctly. */
107 ev.lNetworkEvents = 0xDEADBEEF;
108 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
109 return ev.lNetworkEvents != 0xDEADBEEF;
112 /* Declare data structures for ntdll functions. */
113 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
114 ULONG NamedPipeType;
115 ULONG NamedPipeConfiguration;
116 ULONG MaximumInstances;
117 ULONG CurrentInstances;
118 ULONG InboundQuota;
119 ULONG ReadDataAvailable;
120 ULONG OutboundQuota;
121 ULONG WriteQuotaAvailable;
122 ULONG NamedPipeState;
123 ULONG NamedPipeEnd;
124 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
126 typedef struct _IO_STATUS_BLOCK
128 union {
129 DWORD Status;
130 PVOID Pointer;
131 } u;
132 ULONG_PTR Information;
133 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
135 typedef enum _FILE_INFORMATION_CLASS {
136 FilePipeLocalInformation = 24
137 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
139 typedef DWORD (WINAPI *PNtQueryInformationFile)
140 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
142 # ifndef PIPE_BUF
143 # define PIPE_BUF 512
144 # endif
146 /* Compute revents values for file handle H. If some events cannot happen
147 for the handle, eliminate them from *P_SOUGHT. */
149 static int
150 windows_compute_revents (HANDLE h, int *p_sought)
152 int i, ret, happened;
153 INPUT_RECORD *irbuffer;
154 DWORD avail, nbuffer;
155 BOOL bRet;
156 IO_STATUS_BLOCK iosb;
157 FILE_PIPE_LOCAL_INFORMATION fpli;
158 static PNtQueryInformationFile NtQueryInformationFile;
159 static BOOL once_only;
161 switch (GetFileType (h))
163 case FILE_TYPE_PIPE:
164 if (!once_only)
166 NtQueryInformationFile = (PNtQueryInformationFile)
167 GetProcAddress (GetModuleHandle ("ntdll.dll"),
168 "NtQueryInformationFile");
169 once_only = TRUE;
172 happened = 0;
173 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
175 if (avail)
176 happened |= *p_sought & (POLLIN | POLLRDNORM);
178 else if (GetLastError () == ERROR_BROKEN_PIPE)
179 happened |= POLLHUP;
181 else
183 /* It was the write-end of the pipe. Check if it is writable.
184 If NtQueryInformationFile fails, optimistically assume the pipe is
185 writable. This could happen on Windows 9x, where
186 NtQueryInformationFile is not available, or if we inherit a pipe
187 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
188 (I think this should not happen since Windows XP SP2; WINE seems
189 fine too). Otherwise, ensure that enough space is available for
190 atomic writes. */
191 memset (&iosb, 0, sizeof (iosb));
192 memset (&fpli, 0, sizeof (fpli));
194 if (!NtQueryInformationFile
195 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
196 FilePipeLocalInformation)
197 || fpli.WriteQuotaAvailable >= PIPE_BUF
198 || (fpli.OutboundQuota < PIPE_BUF &&
199 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
200 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
202 return happened;
204 case FILE_TYPE_CHAR:
205 ret = WaitForSingleObject (h, 0);
206 if (!IsConsoleHandle (h))
207 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
209 nbuffer = avail = 0;
210 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
211 if (bRet)
213 /* Input buffer. */
214 *p_sought &= POLLIN | POLLRDNORM;
215 if (nbuffer == 0)
216 return POLLHUP;
217 if (!*p_sought)
218 return 0;
220 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
221 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
222 if (!bRet || avail == 0)
223 return POLLHUP;
225 for (i = 0; i < avail; i++)
226 if (irbuffer[i].EventType == KEY_EVENT)
227 return *p_sought;
228 return 0;
230 else
232 /* Screen buffer. */
233 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
234 return *p_sought;
237 default:
238 ret = WaitForSingleObject (h, 0);
239 if (ret == WAIT_OBJECT_0)
240 return *p_sought & ~(POLLPRI | POLLRDBAND);
242 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
246 /* Convert fd_sets returned by select into revents values. */
248 static int
249 windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
251 int happened = 0;
253 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
254 happened |= (POLLIN | POLLRDNORM) & sought;
256 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
258 int r, error;
260 char data[64];
261 WSASetLastError (0);
262 r = recv (h, data, sizeof (data), MSG_PEEK);
263 error = WSAGetLastError ();
264 WSASetLastError (0);
266 if (r > 0 || error == WSAENOTCONN)
267 happened |= (POLLIN | POLLRDNORM) & sought;
269 /* Distinguish hung-up sockets from other errors. */
270 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
271 || error == WSAECONNABORTED || error == WSAENETRESET)
272 happened |= POLLHUP;
274 else
275 happened |= POLLERR;
278 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
279 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
281 if (lNetworkEvents & FD_OOB)
282 happened |= (POLLPRI | POLLRDBAND) & sought;
284 return happened;
287 #else /* !MinGW */
289 /* Convert select(2) returned fd_sets into poll(2) revents values. */
290 static int
291 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
293 int happened = 0;
294 if (FD_ISSET (fd, rfds))
296 int r;
297 int socket_errno;
299 # if defined __MACH__ && defined __APPLE__
300 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
301 for some kinds of descriptors. Detect if this descriptor is a
302 connected socket, a server socket, or something else using a
303 0-byte recv, and use ioctl(2) to detect POLLHUP. */
304 r = recv (fd, NULL, 0, MSG_PEEK);
305 socket_errno = (r < 0) ? errno : 0;
306 if (r == 0 || socket_errno == ENOTSOCK)
307 ioctl (fd, FIONREAD, &r);
308 # else
309 char data[64];
310 r = recv (fd, data, sizeof (data), MSG_PEEK);
311 socket_errno = (r < 0) ? errno : 0;
312 # endif
313 if (r == 0)
314 happened |= POLLHUP;
316 /* If the event happened on an unconnected server socket,
317 that's fine. */
318 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
319 happened |= (POLLIN | POLLRDNORM) & sought;
321 /* Distinguish hung-up sockets from other errors. */
322 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
323 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
324 happened |= POLLHUP;
326 /* some systems can't use recv() on non-socket, including HP NonStop */
327 else if (socket_errno == ENOTSOCK)
328 happened |= (POLLIN | POLLRDNORM) & sought;
330 else
331 happened |= POLLERR;
334 if (FD_ISSET (fd, wfds))
335 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
337 if (FD_ISSET (fd, efds))
338 happened |= (POLLPRI | POLLRDBAND) & sought;
340 return happened;
342 #endif /* !MinGW */
345 poll (struct pollfd *pfd, nfds_t nfd, int timeout)
347 #ifndef WINDOWS_NATIVE
348 fd_set rfds, wfds, efds;
349 struct timeval tv;
350 struct timeval *ptv;
351 int maxfd, rc;
352 nfds_t i;
354 if (nfd > INT_MAX)
356 errno = EINVAL;
357 return -1;
359 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
360 of a too-large NFD is caught by one of the other checks below, and
361 checking directly for getdtablesize is too much of a portability
362 and/or performance and/or correctness hassle. */
364 /* EFAULT is not necessary to implement, but let's do it in the
365 simplest case. */
366 if (!pfd && nfd)
368 errno = EFAULT;
369 return -1;
372 /* convert timeout number into a timeval structure */
373 if (timeout == 0)
375 ptv = &tv;
376 ptv->tv_sec = 0;
377 ptv->tv_usec = 0;
379 else if (timeout > 0)
381 ptv = &tv;
382 ptv->tv_sec = timeout / 1000;
383 ptv->tv_usec = (timeout % 1000) * 1000;
385 else if (timeout == INFTIM)
386 /* wait forever */
387 ptv = NULL;
388 else
390 errno = EINVAL;
391 return -1;
394 /* create fd sets and determine max fd */
395 maxfd = -1;
396 FD_ZERO (&rfds);
397 FD_ZERO (&wfds);
398 FD_ZERO (&efds);
399 for (i = 0; i < nfd; i++)
401 if (pfd[i].fd < 0)
402 continue;
403 if (maxfd < pfd[i].fd)
405 maxfd = pfd[i].fd;
406 if (FD_SETSIZE <= maxfd)
408 errno = EINVAL;
409 return -1;
412 if (pfd[i].events & (POLLIN | POLLRDNORM))
413 FD_SET (pfd[i].fd, &rfds);
414 /* see select(2): "the only exceptional condition detectable
415 is out-of-band data received on a socket", hence we push
416 POLLWRBAND events onto wfds instead of efds. */
417 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
418 FD_SET (pfd[i].fd, &wfds);
419 if (pfd[i].events & (POLLPRI | POLLRDBAND))
420 FD_SET (pfd[i].fd, &efds);
423 /* examine fd sets */
424 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
425 if (rc < 0)
426 return rc;
428 /* establish results */
429 rc = 0;
430 for (i = 0; i < nfd; i++)
432 pfd[i].revents = (pfd[i].fd < 0
434 : compute_revents (pfd[i].fd, pfd[i].events,
435 &rfds, &wfds, &efds));
436 rc += pfd[i].revents != 0;
439 return rc;
440 #else
441 static struct timeval tv0;
442 static HANDLE hEvent;
443 WSANETWORKEVENTS ev;
444 HANDLE h, handle_array[FD_SETSIZE + 2];
445 DWORD ret, wait_timeout, nhandles;
446 fd_set rfds, wfds, xfds;
447 BOOL poll_again;
448 MSG msg;
449 int rc = 0;
450 nfds_t i;
452 if (nfd > INT_MAX || timeout < -1)
454 errno = EINVAL;
455 return -1;
458 if (!hEvent)
459 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
461 restart:
462 handle_array[0] = hEvent;
463 nhandles = 1;
464 FD_ZERO (&rfds);
465 FD_ZERO (&wfds);
466 FD_ZERO (&xfds);
468 /* Classify socket handles and create fd sets. */
469 for (i = 0; i < nfd; i++)
471 int sought = pfd[i].events;
472 pfd[i].revents = 0;
473 if (pfd[i].fd < 0)
474 continue;
475 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
476 | POLLPRI | POLLRDBAND)))
477 continue;
479 h = (HANDLE) _get_osfhandle (pfd[i].fd);
480 assure (h != NULL);
481 if (IsSocketHandle (h))
483 int requested = FD_CLOSE;
485 /* see above; socket handles are mapped onto select. */
486 if (sought & (POLLIN | POLLRDNORM))
488 requested |= FD_READ | FD_ACCEPT;
489 FD_SET ((SOCKET) h, &rfds);
491 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
493 requested |= FD_WRITE | FD_CONNECT;
494 FD_SET ((SOCKET) h, &wfds);
496 if (sought & (POLLPRI | POLLRDBAND))
498 requested |= FD_OOB;
499 FD_SET ((SOCKET) h, &xfds);
502 if (requested)
503 WSAEventSelect ((SOCKET) h, hEvent, requested);
505 else
507 /* Poll now. If we get an event, do not poll again. Also,
508 screen buffer handles are waitable, and they'll block until
509 a character is available. windows_compute_revents eliminates
510 bits for the "wrong" direction. */
511 pfd[i].revents = windows_compute_revents (h, &sought);
512 if (sought)
513 handle_array[nhandles++] = h;
514 if (pfd[i].revents)
515 timeout = 0;
519 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
521 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
522 no need to call select again. */
523 poll_again = FALSE;
524 wait_timeout = 0;
526 else
528 poll_again = TRUE;
529 if (timeout == INFTIM)
530 wait_timeout = INFINITE;
531 else
532 wait_timeout = timeout;
535 for (;;)
537 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
538 wait_timeout, QS_ALLINPUT);
540 if (ret == WAIT_OBJECT_0 + nhandles)
542 /* new input of some other kind */
543 BOOL bRet;
544 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
546 TranslateMessage (&msg);
547 DispatchMessage (&msg);
550 else
551 break;
554 if (poll_again)
555 select (0, &rfds, &wfds, &xfds, &tv0);
557 /* Place a sentinel at the end of the array. */
558 handle_array[nhandles] = NULL;
559 nhandles = 1;
560 for (i = 0; i < nfd; i++)
562 int happened;
564 if (pfd[i].fd < 0)
565 continue;
566 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
567 POLLOUT | POLLWRNORM | POLLWRBAND)))
568 continue;
570 h = (HANDLE) _get_osfhandle (pfd[i].fd);
571 if (h != handle_array[nhandles])
573 /* It's a socket. */
574 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
575 WSAEventSelect ((SOCKET) h, 0, 0);
577 /* If we're lucky, WSAEnumNetworkEvents already provided a way
578 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
579 if (FD_ISSET ((SOCKET) h, &rfds)
580 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
581 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
582 if (FD_ISSET ((SOCKET) h, &wfds))
583 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
584 if (FD_ISSET ((SOCKET) h, &xfds))
585 ev.lNetworkEvents |= FD_OOB;
587 happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
588 ev.lNetworkEvents);
590 else
592 /* Not a socket. */
593 int sought = pfd[i].events;
594 happened = windows_compute_revents (h, &sought);
595 nhandles++;
598 if ((pfd[i].revents |= happened) != 0)
599 rc++;
602 if (!rc && timeout == INFTIM)
604 SleepEx (1, TRUE);
605 goto restart;
608 return rc;
609 #endif