1 /* Emulation for poll(2)
2    Contributed by Paolo Bonzini.
3 
4    Copyright 2001-2003, 2006-2020 Free Software Foundation, Inc.
5 
6    This file is part of gnulib.
7 
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 3, or (at your option)
11    any later version.
12 
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.
17 
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/>.  */
20 
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
25 
26 #include <config.h>
27 #include <alloca.h>
28 
29 #include <sys/types.h>
30 
31 /* Specification.  */
32 #include <poll.h>
33 
34 #include <errno.h>
35 #include <limits.h>
36 
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
53 
54 #include <sys/select.h>
55 #include <sys/socket.h>
56 
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
63 
64 #include <time.h>
65 
66 #include "assure.h"
67 
68 #ifndef INFTIM
69 # define INFTIM (-1)
70 #endif
71 
72 /* BeOS does not have MSG_PEEK.  */
73 #ifndef MSG_PEEK
74 # define MSG_PEEK 0
75 #endif
76 
77 #ifdef WINDOWS_NATIVE
78 
79 /* Don't assume that UNICODE is not defined.  */
80 # undef GetModuleHandle
81 # define GetModuleHandle GetModuleHandleA
82 # undef PeekConsoleInput
83 # define PeekConsoleInput PeekConsoleInputA
84 # undef CreateEvent
85 # define CreateEvent CreateEventA
86 # undef PeekMessage
87 # define PeekMessage PeekMessageA
88 # undef DispatchMessage
89 # define DispatchMessage DispatchMessageA
90 
91 /* Do *not* use the function WSAPoll
92    <https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsapoll>
93    because there is a bug named “Windows 8 Bugs 309411 - WSAPoll does not
94    report failed connections” that Microsoft won't fix.
95    See Daniel Stenberg: "WASPoll is broken"
96    <https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/>.  */
97 
98 /* Here we need the recv() function from Windows, that takes a SOCKET as
99    first argument, not any possible gnulib override.  */
100 # undef recv
101 
102 /* Here we need the select() function from Windows, because we pass bit masks
103    of SOCKETs, not bit masks of FDs.  */
104 # undef select
105 
106 /* Here we need timeval from Windows since this is what the select() function
107    from Windows requires.  */
108 # undef timeval
109 
110 /* Avoid warnings from gcc -Wcast-function-type.  */
111 # define GetProcAddress \
112    (void *) GetProcAddress
113 
IsConsoleHandle(HANDLE h)114 static BOOL IsConsoleHandle (HANDLE h)
115 {
116   DWORD mode;
117   return GetConsoleMode (h, &mode) != 0;
118 }
119 
120 static BOOL
IsSocketHandle(HANDLE h)121 IsSocketHandle (HANDLE h)
122 {
123   WSANETWORKEVENTS ev;
124 
125   if (IsConsoleHandle (h))
126     return FALSE;
127 
128   /* Under Wine, it seems that getsockopt returns 0 for pipes too.
129      WSAEnumNetworkEvents instead distinguishes the two correctly.  */
130   ev.lNetworkEvents = 0xDEADBEEF;
131   WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
132   return ev.lNetworkEvents != 0xDEADBEEF;
133 }
134 
135 /* Declare data structures for ntdll functions.  */
136 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
137   ULONG NamedPipeType;
138   ULONG NamedPipeConfiguration;
139   ULONG MaximumInstances;
140   ULONG CurrentInstances;
141   ULONG InboundQuota;
142   ULONG ReadDataAvailable;
143   ULONG OutboundQuota;
144   ULONG WriteQuotaAvailable;
145   ULONG NamedPipeState;
146   ULONG NamedPipeEnd;
147 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
148 
149 typedef struct _IO_STATUS_BLOCK
150 {
151   union {
152     DWORD Status;
153     PVOID Pointer;
154   } u;
155   ULONG_PTR Information;
156 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
157 
158 typedef enum _FILE_INFORMATION_CLASS {
159   FilePipeLocalInformation = 24
160 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
161 
162 typedef DWORD (WINAPI *PNtQueryInformationFile)
163          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
164 
165 # ifndef PIPE_BUF
166 #  define PIPE_BUF      512
167 # endif
168 
169 /* Compute revents values for file handle H.  If some events cannot happen
170    for the handle, eliminate them from *P_SOUGHT.  */
171 
172 static int
windows_compute_revents(HANDLE h,int * p_sought)173 windows_compute_revents (HANDLE h, int *p_sought)
174 {
175   int i, ret, happened;
176   INPUT_RECORD *irbuffer;
177   DWORD avail, nbuffer;
178   BOOL bRet;
179   IO_STATUS_BLOCK iosb;
180   FILE_PIPE_LOCAL_INFORMATION fpli;
181   static PNtQueryInformationFile NtQueryInformationFile;
182   static BOOL once_only;
183 
184   switch (GetFileType (h))
185     {
186     case FILE_TYPE_PIPE:
187       if (!once_only)
188         {
189           NtQueryInformationFile = (PNtQueryInformationFile)
190             GetProcAddress (GetModuleHandle ("ntdll.dll"),
191                             "NtQueryInformationFile");
192           once_only = TRUE;
193         }
194 
195       happened = 0;
196       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
197         {
198           if (avail)
199             happened |= *p_sought & (POLLIN | POLLRDNORM);
200         }
201       else if (GetLastError () == ERROR_BROKEN_PIPE)
202         happened |= POLLHUP;
203 
204       else
205         {
206           /* It was the write-end of the pipe.  Check if it is writable.
207              If NtQueryInformationFile fails, optimistically assume the pipe is
208              writable.  This could happen on Windows 9x, where
209              NtQueryInformationFile is not available, or if we inherit a pipe
210              that doesn't permit FILE_READ_ATTRIBUTES access on the write end
211              (I think this should not happen since Windows XP SP2; WINE seems
212              fine too).  Otherwise, ensure that enough space is available for
213              atomic writes.  */
214           memset (&iosb, 0, sizeof (iosb));
215           memset (&fpli, 0, sizeof (fpli));
216 
217           if (!NtQueryInformationFile
218               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
219                                          FilePipeLocalInformation)
220               || fpli.WriteQuotaAvailable >= PIPE_BUF
221               || (fpli.OutboundQuota < PIPE_BUF &&
222                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
223             happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
224         }
225       return happened;
226 
227     case FILE_TYPE_CHAR:
228       ret = WaitForSingleObject (h, 0);
229       if (!IsConsoleHandle (h))
230         return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
231 
232       nbuffer = avail = 0;
233       bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
234       if (bRet)
235         {
236           /* Input buffer.  */
237           *p_sought &= POLLIN | POLLRDNORM;
238           if (nbuffer == 0)
239             return POLLHUP;
240           if (!*p_sought)
241             return 0;
242 
243           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
244           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
245           if (!bRet || avail == 0)
246             return POLLHUP;
247 
248           for (i = 0; i < avail; i++)
249             if (irbuffer[i].EventType == KEY_EVENT)
250               return *p_sought;
251           return 0;
252         }
253       else
254         {
255           /* Screen buffer.  */
256           *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
257           return *p_sought;
258         }
259 
260     default:
261       ret = WaitForSingleObject (h, 0);
262       if (ret == WAIT_OBJECT_0)
263         return *p_sought & ~(POLLPRI | POLLRDBAND);
264 
265       return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
266     }
267 }
268 
269 /* Convert fd_sets returned by select into revents values.  */
270 
271 static int
windows_compute_revents_socket(SOCKET h,int sought,long lNetworkEvents)272 windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
273 {
274   int happened = 0;
275 
276   if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
277     happened |= (POLLIN | POLLRDNORM) & sought;
278 
279   else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
280     {
281       int r, error;
282 
283       char data[64];
284       WSASetLastError (0);
285       r = recv (h, data, sizeof (data), MSG_PEEK);
286       error = WSAGetLastError ();
287       WSASetLastError (0);
288 
289       if (r > 0 || error == WSAENOTCONN)
290         happened |= (POLLIN | POLLRDNORM) & sought;
291 
292       /* Distinguish hung-up sockets from other errors.  */
293       else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
294                || error == WSAECONNABORTED || error == WSAENETRESET)
295         happened |= POLLHUP;
296 
297       else
298         happened |= POLLERR;
299     }
300 
301   if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
302     happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
303 
304   if (lNetworkEvents & FD_OOB)
305     happened |= (POLLPRI | POLLRDBAND) & sought;
306 
307   return happened;
308 }
309 
310 #else /* !MinGW */
311 
312 /* Convert select(2) returned fd_sets into poll(2) revents values.  */
313 static int
compute_revents(int fd,int sought,fd_set * rfds,fd_set * wfds,fd_set * efds)314 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
315 {
316   int happened = 0;
317   if (FD_ISSET (fd, rfds))
318     {
319       int r;
320       int socket_errno;
321 
322 # if defined __MACH__ && defined __APPLE__
323       /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
324          for some kinds of descriptors.  Detect if this descriptor is a
325          connected socket, a server socket, or something else using a
326          0-byte recv, and use ioctl(2) to detect POLLHUP.  */
327       r = recv (fd, NULL, 0, MSG_PEEK);
328       socket_errno = (r < 0) ? errno : 0;
329       if (r == 0 || socket_errno == ENOTSOCK)
330         ioctl (fd, FIONREAD, &r);
331 # else
332       char data[64];
333       r = recv (fd, data, sizeof (data), MSG_PEEK);
334       socket_errno = (r < 0) ? errno : 0;
335 # endif
336       if (r == 0)
337         happened |= POLLHUP;
338 
339       /* If the event happened on an unconnected server socket,
340          that's fine. */
341       else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
342         happened |= (POLLIN | POLLRDNORM) & sought;
343 
344       /* Distinguish hung-up sockets from other errors.  */
345       else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
346                || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
347         happened |= POLLHUP;
348 
349       /* some systems can't use recv() on non-socket, including HP NonStop */
350       else if (socket_errno == ENOTSOCK)
351         happened |= (POLLIN | POLLRDNORM) & sought;
352 
353       else
354         happened |= POLLERR;
355     }
356 
357   if (FD_ISSET (fd, wfds))
358     happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
359 
360   if (FD_ISSET (fd, efds))
361     happened |= (POLLPRI | POLLRDBAND) & sought;
362 
363   return happened;
364 }
365 #endif /* !MinGW */
366 
367 int
poll(struct pollfd * pfd,nfds_t nfd,int timeout)368 poll (struct pollfd *pfd, nfds_t nfd, int timeout)
369 {
370 #ifndef WINDOWS_NATIVE
371   fd_set rfds, wfds, efds;
372   struct timeval tv;
373   struct timeval *ptv;
374   int maxfd, rc;
375   nfds_t i;
376 
377   if (nfd > INT_MAX)
378     {
379       errno = EINVAL;
380       return -1;
381     }
382   /* Don't check directly for NFD greater than OPEN_MAX.  Any practical use
383      of a too-large NFD is caught by one of the other checks below, and
384      checking directly for getdtablesize is too much of a portability
385      and/or performance and/or correctness hassle.  */
386 
387   /* EFAULT is not necessary to implement, but let's do it in the
388      simplest case. */
389   if (!pfd && nfd)
390     {
391       errno = EFAULT;
392       return -1;
393     }
394 
395   /* convert timeout number into a timeval structure */
396   if (timeout == 0)
397     {
398       ptv = &tv;
399       ptv->tv_sec = 0;
400       ptv->tv_usec = 0;
401     }
402   else if (timeout > 0)
403     {
404       ptv = &tv;
405       ptv->tv_sec = timeout / 1000;
406       ptv->tv_usec = (timeout % 1000) * 1000;
407     }
408   else if (timeout == INFTIM)
409     /* wait forever */
410     ptv = NULL;
411   else
412     {
413       errno = EINVAL;
414       return -1;
415     }
416 
417   /* create fd sets and determine max fd */
418   maxfd = -1;
419   FD_ZERO (&rfds);
420   FD_ZERO (&wfds);
421   FD_ZERO (&efds);
422   for (i = 0; i < nfd; i++)
423     {
424       if (pfd[i].fd < 0)
425         continue;
426       if (maxfd < pfd[i].fd)
427         {
428           maxfd = pfd[i].fd;
429           if (FD_SETSIZE <= maxfd)
430             {
431               errno = EINVAL;
432               return -1;
433             }
434         }
435       if (pfd[i].events & (POLLIN | POLLRDNORM))
436         FD_SET (pfd[i].fd, &rfds);
437       /* see select(2): "the only exceptional condition detectable
438          is out-of-band data received on a socket", hence we push
439          POLLWRBAND events onto wfds instead of efds. */
440       if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
441         FD_SET (pfd[i].fd, &wfds);
442       if (pfd[i].events & (POLLPRI | POLLRDBAND))
443         FD_SET (pfd[i].fd, &efds);
444     }
445 
446   /* examine fd sets */
447   rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
448   if (rc < 0)
449     return rc;
450 
451   /* establish results */
452   rc = 0;
453   for (i = 0; i < nfd; i++)
454     {
455       pfd[i].revents = (pfd[i].fd < 0
456                         ? 0
457                         : compute_revents (pfd[i].fd, pfd[i].events,
458                                            &rfds, &wfds, &efds));
459       rc += pfd[i].revents != 0;
460     }
461 
462   return rc;
463 #else
464   static struct timeval tv0;
465   static HANDLE hEvent;
466   WSANETWORKEVENTS ev;
467   HANDLE h, handle_array[FD_SETSIZE + 2];
468   DWORD ret, wait_timeout, nhandles;
469   fd_set rfds, wfds, xfds;
470   BOOL poll_again;
471   MSG msg;
472   int rc = 0;
473   nfds_t i;
474 
475   if (nfd > INT_MAX || timeout < -1)
476     {
477       errno = EINVAL;
478       return -1;
479     }
480 
481   if (!hEvent)
482     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
483 
484 restart:
485   handle_array[0] = hEvent;
486   nhandles = 1;
487   FD_ZERO (&rfds);
488   FD_ZERO (&wfds);
489   FD_ZERO (&xfds);
490 
491   /* Classify socket handles and create fd sets. */
492   for (i = 0; i < nfd; i++)
493     {
494       int sought = pfd[i].events;
495       pfd[i].revents = 0;
496       if (pfd[i].fd < 0)
497         continue;
498       if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
499                       | POLLPRI | POLLRDBAND)))
500         continue;
501 
502       h = (HANDLE) _get_osfhandle (pfd[i].fd);
503       assure (h != NULL);
504       if (IsSocketHandle (h))
505         {
506           int requested = FD_CLOSE;
507 
508           /* see above; socket handles are mapped onto select.  */
509           if (sought & (POLLIN | POLLRDNORM))
510             {
511               requested |= FD_READ | FD_ACCEPT;
512               FD_SET ((SOCKET) h, &rfds);
513             }
514           if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
515             {
516               requested |= FD_WRITE | FD_CONNECT;
517               FD_SET ((SOCKET) h, &wfds);
518             }
519           if (sought & (POLLPRI | POLLRDBAND))
520             {
521               requested |= FD_OOB;
522               FD_SET ((SOCKET) h, &xfds);
523             }
524 
525           if (requested)
526             WSAEventSelect ((SOCKET) h, hEvent, requested);
527         }
528       else
529         {
530           /* Poll now.  If we get an event, do not poll again.  Also,
531              screen buffer handles are waitable, and they'll block until
532              a character is available.  windows_compute_revents eliminates
533              bits for the "wrong" direction. */
534           pfd[i].revents = windows_compute_revents (h, &sought);
535           if (sought)
536             handle_array[nhandles++] = h;
537           if (pfd[i].revents)
538             timeout = 0;
539         }
540     }
541 
542   if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
543     {
544       /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
545          no need to call select again.  */
546       poll_again = FALSE;
547       wait_timeout = 0;
548     }
549   else
550     {
551       poll_again = TRUE;
552       if (timeout == INFTIM)
553         wait_timeout = INFINITE;
554       else
555         wait_timeout = timeout;
556     }
557 
558   for (;;)
559     {
560       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
561                                        wait_timeout, QS_ALLINPUT);
562 
563       if (ret == WAIT_OBJECT_0 + nhandles)
564         {
565           /* new input of some other kind */
566           BOOL bRet;
567           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
568             {
569               TranslateMessage (&msg);
570               DispatchMessage (&msg);
571             }
572         }
573       else
574         break;
575     }
576 
577   if (poll_again)
578     select (0, &rfds, &wfds, &xfds, &tv0);
579 
580   /* Place a sentinel at the end of the array.  */
581   handle_array[nhandles] = NULL;
582   nhandles = 1;
583   for (i = 0; i < nfd; i++)
584     {
585       int happened;
586 
587       if (pfd[i].fd < 0)
588         continue;
589       if (!(pfd[i].events & (POLLIN | POLLRDNORM |
590                              POLLOUT | POLLWRNORM | POLLWRBAND)))
591         continue;
592 
593       h = (HANDLE) _get_osfhandle (pfd[i].fd);
594       if (h != handle_array[nhandles])
595         {
596           /* It's a socket.  */
597           WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
598           WSAEventSelect ((SOCKET) h, 0, 0);
599 
600           /* If we're lucky, WSAEnumNetworkEvents already provided a way
601              to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
602           if (FD_ISSET ((SOCKET) h, &rfds)
603               && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
604             ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
605           if (FD_ISSET ((SOCKET) h, &wfds))
606             ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
607           if (FD_ISSET ((SOCKET) h, &xfds))
608             ev.lNetworkEvents |= FD_OOB;
609 
610           happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
611                                                      ev.lNetworkEvents);
612         }
613       else
614         {
615           /* Not a socket.  */
616           int sought = pfd[i].events;
617           happened = windows_compute_revents (h, &sought);
618           nhandles++;
619         }
620 
621        if ((pfd[i].revents |= happened) != 0)
622         rc++;
623     }
624 
625   if (!rc && timeout == INFTIM)
626     {
627       SleepEx (1, TRUE);
628       goto restart;
629     }
630 
631   return rc;
632 #endif
633 }
634