Ensure Automake does not drop ~~gnulib.m4.
[gnulib.git] / lib / poll.c
blob53bbafee2fc694aaae696ce66092efdfcd967133
1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2020 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 /* Do *not* use the function WSAPoll
80 <https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsapoll>
81 because there is a bug named “Windows 8 Bugs 309411 - WSAPoll does not
82 report failed connections” that Microsoft won't fix.
83 See Daniel Stenberg: "WASPoll is broken"
84 <https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/>. */
86 /* Here we need the recv() function from Windows, that takes a SOCKET as
87 first argument, not any possible gnulib override. */
88 # undef recv
90 /* Here we need the select() function from Windows, because we pass bit masks
91 of SOCKETs, not bit masks of FDs. */
92 # undef select
94 /* Here we need timeval from Windows since this is what the select() function
95 from Windows requires. */
96 # undef timeval
98 /* Avoid warnings from gcc -Wcast-function-type. */
99 # define GetProcAddress \
100 (void *) GetProcAddress
102 static BOOL IsConsoleHandle (HANDLE h)
104 DWORD mode;
105 return GetConsoleMode (h, &mode) != 0;
108 static BOOL
109 IsSocketHandle (HANDLE h)
111 WSANETWORKEVENTS ev;
113 if (IsConsoleHandle (h))
114 return FALSE;
116 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
117 WSAEnumNetworkEvents instead distinguishes the two correctly. */
118 ev.lNetworkEvents = 0xDEADBEEF;
119 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
120 return ev.lNetworkEvents != 0xDEADBEEF;
123 /* Declare data structures for ntdll functions. */
124 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
125 ULONG NamedPipeType;
126 ULONG NamedPipeConfiguration;
127 ULONG MaximumInstances;
128 ULONG CurrentInstances;
129 ULONG InboundQuota;
130 ULONG ReadDataAvailable;
131 ULONG OutboundQuota;
132 ULONG WriteQuotaAvailable;
133 ULONG NamedPipeState;
134 ULONG NamedPipeEnd;
135 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
137 typedef struct _IO_STATUS_BLOCK
139 union {
140 DWORD Status;
141 PVOID Pointer;
142 } u;
143 ULONG_PTR Information;
144 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
146 typedef enum _FILE_INFORMATION_CLASS {
147 FilePipeLocalInformation = 24
148 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
150 typedef DWORD (WINAPI *PNtQueryInformationFile)
151 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
153 # ifndef PIPE_BUF
154 # define PIPE_BUF 512
155 # endif
157 /* Compute revents values for file handle H. If some events cannot happen
158 for the handle, eliminate them from *P_SOUGHT. */
160 static int
161 windows_compute_revents (HANDLE h, int *p_sought)
163 int i, ret, happened;
164 INPUT_RECORD *irbuffer;
165 DWORD avail, nbuffer;
166 BOOL bRet;
167 IO_STATUS_BLOCK iosb;
168 FILE_PIPE_LOCAL_INFORMATION fpli;
169 static PNtQueryInformationFile NtQueryInformationFile;
170 static BOOL once_only;
172 switch (GetFileType (h))
174 case FILE_TYPE_PIPE:
175 if (!once_only)
177 NtQueryInformationFile = (PNtQueryInformationFile)
178 GetProcAddress (GetModuleHandle ("ntdll.dll"),
179 "NtQueryInformationFile");
180 once_only = TRUE;
183 happened = 0;
184 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
186 if (avail)
187 happened |= *p_sought & (POLLIN | POLLRDNORM);
189 else if (GetLastError () == ERROR_BROKEN_PIPE)
190 happened |= POLLHUP;
192 else
194 /* It was the write-end of the pipe. Check if it is writable.
195 If NtQueryInformationFile fails, optimistically assume the pipe is
196 writable. This could happen on Windows 9x, where
197 NtQueryInformationFile is not available, or if we inherit a pipe
198 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
199 (I think this should not happen since Windows XP SP2; WINE seems
200 fine too). Otherwise, ensure that enough space is available for
201 atomic writes. */
202 memset (&iosb, 0, sizeof (iosb));
203 memset (&fpli, 0, sizeof (fpli));
205 if (!NtQueryInformationFile
206 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
207 FilePipeLocalInformation)
208 || fpli.WriteQuotaAvailable >= PIPE_BUF
209 || (fpli.OutboundQuota < PIPE_BUF &&
210 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
211 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
213 return happened;
215 case FILE_TYPE_CHAR:
216 ret = WaitForSingleObject (h, 0);
217 if (!IsConsoleHandle (h))
218 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
220 nbuffer = avail = 0;
221 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
222 if (bRet)
224 /* Input buffer. */
225 *p_sought &= POLLIN | POLLRDNORM;
226 if (nbuffer == 0)
227 return POLLHUP;
228 if (!*p_sought)
229 return 0;
231 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
232 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
233 if (!bRet || avail == 0)
234 return POLLHUP;
236 for (i = 0; i < avail; i++)
237 if (irbuffer[i].EventType == KEY_EVENT)
238 return *p_sought;
239 return 0;
241 else
243 /* Screen buffer. */
244 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
245 return *p_sought;
248 default:
249 ret = WaitForSingleObject (h, 0);
250 if (ret == WAIT_OBJECT_0)
251 return *p_sought & ~(POLLPRI | POLLRDBAND);
253 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
257 /* Convert fd_sets returned by select into revents values. */
259 static int
260 windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
262 int happened = 0;
264 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
265 happened |= (POLLIN | POLLRDNORM) & sought;
267 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
269 int r, error;
271 char data[64];
272 WSASetLastError (0);
273 r = recv (h, data, sizeof (data), MSG_PEEK);
274 error = WSAGetLastError ();
275 WSASetLastError (0);
277 if (r > 0 || error == WSAENOTCONN)
278 happened |= (POLLIN | POLLRDNORM) & sought;
280 /* Distinguish hung-up sockets from other errors. */
281 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
282 || error == WSAECONNABORTED || error == WSAENETRESET)
283 happened |= POLLHUP;
285 else
286 happened |= POLLERR;
289 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
290 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
292 if (lNetworkEvents & FD_OOB)
293 happened |= (POLLPRI | POLLRDBAND) & sought;
295 return happened;
298 #else /* !MinGW */
300 /* Convert select(2) returned fd_sets into poll(2) revents values. */
301 static int
302 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
304 int happened = 0;
305 if (FD_ISSET (fd, rfds))
307 int r;
308 int socket_errno;
310 # if defined __MACH__ && defined __APPLE__
311 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
312 for some kinds of descriptors. Detect if this descriptor is a
313 connected socket, a server socket, or something else using a
314 0-byte recv, and use ioctl(2) to detect POLLHUP. */
315 r = recv (fd, NULL, 0, MSG_PEEK);
316 socket_errno = (r < 0) ? errno : 0;
317 if (r == 0 || socket_errno == ENOTSOCK)
318 ioctl (fd, FIONREAD, &r);
319 # else
320 char data[64];
321 r = recv (fd, data, sizeof (data), MSG_PEEK);
322 socket_errno = (r < 0) ? errno : 0;
323 # endif
324 if (r == 0)
325 happened |= POLLHUP;
327 /* If the event happened on an unconnected server socket,
328 that's fine. */
329 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
330 happened |= (POLLIN | POLLRDNORM) & sought;
332 /* Distinguish hung-up sockets from other errors. */
333 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
334 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
335 happened |= POLLHUP;
337 /* some systems can't use recv() on non-socket, including HP NonStop */
338 else if (socket_errno == ENOTSOCK)
339 happened |= (POLLIN | POLLRDNORM) & sought;
341 else
342 happened |= POLLERR;
345 if (FD_ISSET (fd, wfds))
346 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
348 if (FD_ISSET (fd, efds))
349 happened |= (POLLPRI | POLLRDBAND) & sought;
351 return happened;
353 #endif /* !MinGW */
356 poll (struct pollfd *pfd, nfds_t nfd, int timeout)
358 #ifndef WINDOWS_NATIVE
359 fd_set rfds, wfds, efds;
360 struct timeval tv;
361 struct timeval *ptv;
362 int maxfd, rc;
363 nfds_t i;
365 if (nfd > INT_MAX)
367 errno = EINVAL;
368 return -1;
370 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
371 of a too-large NFD is caught by one of the other checks below, and
372 checking directly for getdtablesize is too much of a portability
373 and/or performance and/or correctness hassle. */
375 /* EFAULT is not necessary to implement, but let's do it in the
376 simplest case. */
377 if (!pfd && nfd)
379 errno = EFAULT;
380 return -1;
383 /* convert timeout number into a timeval structure */
384 if (timeout == 0)
386 ptv = &tv;
387 ptv->tv_sec = 0;
388 ptv->tv_usec = 0;
390 else if (timeout > 0)
392 ptv = &tv;
393 ptv->tv_sec = timeout / 1000;
394 ptv->tv_usec = (timeout % 1000) * 1000;
396 else if (timeout == INFTIM)
397 /* wait forever */
398 ptv = NULL;
399 else
401 errno = EINVAL;
402 return -1;
405 /* create fd sets and determine max fd */
406 maxfd = -1;
407 FD_ZERO (&rfds);
408 FD_ZERO (&wfds);
409 FD_ZERO (&efds);
410 for (i = 0; i < nfd; i++)
412 if (pfd[i].fd < 0)
413 continue;
414 if (maxfd < pfd[i].fd)
416 maxfd = pfd[i].fd;
417 if (FD_SETSIZE <= maxfd)
419 errno = EINVAL;
420 return -1;
423 if (pfd[i].events & (POLLIN | POLLRDNORM))
424 FD_SET (pfd[i].fd, &rfds);
425 /* see select(2): "the only exceptional condition detectable
426 is out-of-band data received on a socket", hence we push
427 POLLWRBAND events onto wfds instead of efds. */
428 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
429 FD_SET (pfd[i].fd, &wfds);
430 if (pfd[i].events & (POLLPRI | POLLRDBAND))
431 FD_SET (pfd[i].fd, &efds);
434 /* examine fd sets */
435 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
436 if (rc < 0)
437 return rc;
439 /* establish results */
440 rc = 0;
441 for (i = 0; i < nfd; i++)
443 pfd[i].revents = (pfd[i].fd < 0
445 : compute_revents (pfd[i].fd, pfd[i].events,
446 &rfds, &wfds, &efds));
447 rc += pfd[i].revents != 0;
450 return rc;
451 #else
452 static struct timeval tv0;
453 static HANDLE hEvent;
454 WSANETWORKEVENTS ev;
455 HANDLE h, handle_array[FD_SETSIZE + 2];
456 DWORD ret, wait_timeout, nhandles;
457 fd_set rfds, wfds, xfds;
458 BOOL poll_again;
459 MSG msg;
460 int rc = 0;
461 nfds_t i;
463 if (nfd > INT_MAX || timeout < -1)
465 errno = EINVAL;
466 return -1;
469 if (!hEvent)
470 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
472 restart:
473 handle_array[0] = hEvent;
474 nhandles = 1;
475 FD_ZERO (&rfds);
476 FD_ZERO (&wfds);
477 FD_ZERO (&xfds);
479 /* Classify socket handles and create fd sets. */
480 for (i = 0; i < nfd; i++)
482 int sought = pfd[i].events;
483 pfd[i].revents = 0;
484 if (pfd[i].fd < 0)
485 continue;
486 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
487 | POLLPRI | POLLRDBAND)))
488 continue;
490 h = (HANDLE) _get_osfhandle (pfd[i].fd);
491 assure (h != NULL);
492 if (IsSocketHandle (h))
494 int requested = FD_CLOSE;
496 /* see above; socket handles are mapped onto select. */
497 if (sought & (POLLIN | POLLRDNORM))
499 requested |= FD_READ | FD_ACCEPT;
500 FD_SET ((SOCKET) h, &rfds);
502 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
504 requested |= FD_WRITE | FD_CONNECT;
505 FD_SET ((SOCKET) h, &wfds);
507 if (sought & (POLLPRI | POLLRDBAND))
509 requested |= FD_OOB;
510 FD_SET ((SOCKET) h, &xfds);
513 if (requested)
514 WSAEventSelect ((SOCKET) h, hEvent, requested);
516 else
518 /* Poll now. If we get an event, do not poll again. Also,
519 screen buffer handles are waitable, and they'll block until
520 a character is available. windows_compute_revents eliminates
521 bits for the "wrong" direction. */
522 pfd[i].revents = windows_compute_revents (h, &sought);
523 if (sought)
524 handle_array[nhandles++] = h;
525 if (pfd[i].revents)
526 timeout = 0;
530 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
532 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
533 no need to call select again. */
534 poll_again = FALSE;
535 wait_timeout = 0;
537 else
539 poll_again = TRUE;
540 if (timeout == INFTIM)
541 wait_timeout = INFINITE;
542 else
543 wait_timeout = timeout;
546 for (;;)
548 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
549 wait_timeout, QS_ALLINPUT);
551 if (ret == WAIT_OBJECT_0 + nhandles)
553 /* new input of some other kind */
554 BOOL bRet;
555 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
557 TranslateMessage (&msg);
558 DispatchMessage (&msg);
561 else
562 break;
565 if (poll_again)
566 select (0, &rfds, &wfds, &xfds, &tv0);
568 /* Place a sentinel at the end of the array. */
569 handle_array[nhandles] = NULL;
570 nhandles = 1;
571 for (i = 0; i < nfd; i++)
573 int happened;
575 if (pfd[i].fd < 0)
576 continue;
577 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
578 POLLOUT | POLLWRNORM | POLLWRBAND)))
579 continue;
581 h = (HANDLE) _get_osfhandle (pfd[i].fd);
582 if (h != handle_array[nhandles])
584 /* It's a socket. */
585 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
586 WSAEventSelect ((SOCKET) h, 0, 0);
588 /* If we're lucky, WSAEnumNetworkEvents already provided a way
589 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
590 if (FD_ISSET ((SOCKET) h, &rfds)
591 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
592 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
593 if (FD_ISSET ((SOCKET) h, &wfds))
594 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
595 if (FD_ISSET ((SOCKET) h, &xfds))
596 ev.lNetworkEvents |= FD_OOB;
598 happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
599 ev.lNetworkEvents);
601 else
603 /* Not a socket. */
604 int sought = pfd[i].events;
605 happened = windows_compute_revents (h, &sought);
606 nhandles++;
609 if ((pfd[i].revents |= happened) != 0)
610 rc++;
613 if (!rc && timeout == INFTIM)
615 SleepEx (1, TRUE);
616 goto restart;
619 return rc;
620 #endif