Code

Merge branch 'maint'
[git.git] / compat / win32 / sys / poll.c
1 /* Emulation for poll(2)
2    Contributed by Paolo Bonzini.
4    Copyright 2001-2003, 2006-2010 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 <malloc.h>
29 #include <sys/types.h>
30 #include "poll.h"
31 #include <errno.h>
32 #include <limits.h>
33 #include <assert.h>
35 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
36 # define WIN32_NATIVE
37 # include <winsock2.h>
38 # include <windows.h>
39 # include <io.h>
40 # include <stdio.h>
41 # include <conio.h>
42 #else
43 # include <sys/time.h>
44 # include <sys/socket.h>
45 # include <sys/select.h>
46 # include <unistd.h>
47 #endif
49 #ifdef HAVE_SYS_IOCTL_H
50 # include <sys/ioctl.h>
51 #endif
52 #ifdef HAVE_SYS_FILIO_H
53 # include <sys/filio.h>
54 #endif
56 #include <time.h>
58 #ifndef INFTIM
59 # define INFTIM (-1)
60 #endif
62 /* BeOS does not have MSG_PEEK.  */
63 #ifndef MSG_PEEK
64 # define MSG_PEEK 0
65 #endif
67 #ifdef WIN32_NATIVE
69 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
71 static BOOL
72 IsSocketHandle (HANDLE h)
73 {
74   WSANETWORKEVENTS ev;
76   if (IsConsoleHandle (h))
77     return FALSE;
79   /* Under Wine, it seems that getsockopt returns 0 for pipes too.
80      WSAEnumNetworkEvents instead distinguishes the two correctly.  */
81   ev.lNetworkEvents = 0xDEADBEEF;
82   WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
83   return ev.lNetworkEvents != 0xDEADBEEF;
84 }
86 /* Declare data structures for ntdll functions.  */
87 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
88   ULONG NamedPipeType;
89   ULONG NamedPipeConfiguration;
90   ULONG MaximumInstances;
91   ULONG CurrentInstances;
92   ULONG InboundQuota;
93   ULONG ReadDataAvailable;
94   ULONG OutboundQuota;
95   ULONG WriteQuotaAvailable;
96   ULONG NamedPipeState;
97   ULONG NamedPipeEnd;
98 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
100 typedef struct _IO_STATUS_BLOCK
102   union {
103     DWORD Status;
104     PVOID Pointer;
105   } u;
106   ULONG_PTR Information;
107 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
109 typedef enum _FILE_INFORMATION_CLASS {
110   FilePipeLocalInformation = 24
111 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
113 typedef DWORD (WINAPI *PNtQueryInformationFile)
114          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
116 # ifndef PIPE_BUF
117 #  define PIPE_BUF      512
118 # endif
120 /* Compute revents values for file handle H.  If some events cannot happen
121    for the handle, eliminate them from *P_SOUGHT.  */
123 static int
124 win32_compute_revents (HANDLE h, int *p_sought)
126   int i, ret, happened;
127   INPUT_RECORD *irbuffer;
128   DWORD avail, nbuffer;
129   BOOL bRet;
130   IO_STATUS_BLOCK iosb;
131   FILE_PIPE_LOCAL_INFORMATION fpli;
132   static PNtQueryInformationFile NtQueryInformationFile;
133   static BOOL once_only;
135   switch (GetFileType (h))
136     {
137     case FILE_TYPE_PIPE:
138       if (!once_only)
139         {
140           NtQueryInformationFile = (PNtQueryInformationFile)
141             GetProcAddress (GetModuleHandle ("ntdll.dll"),
142                             "NtQueryInformationFile");
143           once_only = TRUE;
144         }
146       happened = 0;
147       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
148         {
149           if (avail)
150             happened |= *p_sought & (POLLIN | POLLRDNORM);
151         }
152       else if (GetLastError () == ERROR_BROKEN_PIPE)
153         happened |= POLLHUP;
155       else
156         {
157           /* It was the write-end of the pipe.  Check if it is writable.
158              If NtQueryInformationFile fails, optimistically assume the pipe is
159              writable.  This could happen on Win9x, where NtQueryInformationFile
160              is not available, or if we inherit a pipe that doesn't permit
161              FILE_READ_ATTRIBUTES access on the write end (I think this should
162              not happen since WinXP SP2; WINE seems fine too).  Otherwise,
163              ensure that enough space is available for atomic writes.  */
164           memset (&iosb, 0, sizeof (iosb));
165           memset (&fpli, 0, sizeof (fpli));
167           if (!NtQueryInformationFile
168               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
169                                          FilePipeLocalInformation)
170               || fpli.WriteQuotaAvailable >= PIPE_BUF
171               || (fpli.OutboundQuota < PIPE_BUF &&
172                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
173             happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
174         }
175       return happened;
177     case FILE_TYPE_CHAR:
178       ret = WaitForSingleObject (h, 0);
179       if (!IsConsoleHandle (h))
180         return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
182       nbuffer = avail = 0;
183       bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
184       if (bRet)
185         {
186           /* Input buffer.  */
187           *p_sought &= POLLIN | POLLRDNORM;
188           if (nbuffer == 0)
189             return POLLHUP;
190           if (!*p_sought)
191             return 0;
193           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
194           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
195           if (!bRet || avail == 0)
196             return POLLHUP;
198           for (i = 0; i < avail; i++)
199             if (irbuffer[i].EventType == KEY_EVENT)
200               return *p_sought;
201           return 0;
202         }
203       else
204         {
205           /* Screen buffer.  */
206           *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
207           return *p_sought;
208         }
210     default:
211       ret = WaitForSingleObject (h, 0);
212       if (ret == WAIT_OBJECT_0)
213         return *p_sought & ~(POLLPRI | POLLRDBAND);
215       return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
216     }
219 /* Convert fd_sets returned by select into revents values.  */
221 static int
222 win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
224   int happened = 0;
226   if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
227     happened |= (POLLIN | POLLRDNORM) & sought;
229   else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
230     {
231       int r, error;
233       char data[64];
234       WSASetLastError (0);
235       r = recv (h, data, sizeof (data), MSG_PEEK);
236       error = WSAGetLastError ();
237       WSASetLastError (0);
239       if (r > 0 || error == WSAENOTCONN)
240         happened |= (POLLIN | POLLRDNORM) & sought;
242       /* Distinguish hung-up sockets from other errors.  */
243       else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
244                || error == WSAECONNABORTED || error == WSAENETRESET)
245         happened |= POLLHUP;
247       else
248         happened |= POLLERR;
249     }
251   if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
252     happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
254   if (lNetworkEvents & FD_OOB)
255     happened |= (POLLPRI | POLLRDBAND) & sought;
257   return happened;
260 #else /* !MinGW */
262 /* Convert select(2) returned fd_sets into poll(2) revents values.  */
263 static int
264 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
266   int happened = 0;
267   if (FD_ISSET (fd, rfds))
268     {
269       int r;
270       int socket_errno;
272 # if defined __MACH__ && defined __APPLE__
273       /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
274          for some kinds of descriptors.  Detect if this descriptor is a
275          connected socket, a server socket, or something else using a
276          0-byte recv, and use ioctl(2) to detect POLLHUP.  */
277       r = recv (fd, NULL, 0, MSG_PEEK);
278       socket_errno = (r < 0) ? errno : 0;
279       if (r == 0 || socket_errno == ENOTSOCK)
280         ioctl (fd, FIONREAD, &r);
281 # else
282       char data[64];
283       r = recv (fd, data, sizeof (data), MSG_PEEK);
284       socket_errno = (r < 0) ? errno : 0;
285 # endif
286       if (r == 0)
287         happened |= POLLHUP;
289       /* If the event happened on an unconnected server socket,
290          that's fine. */
291       else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
292         happened |= (POLLIN | POLLRDNORM) & sought;
294       /* Distinguish hung-up sockets from other errors.  */
295       else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
296                || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
297         happened |= POLLHUP;
299       else
300         happened |= POLLERR;
301     }
303   if (FD_ISSET (fd, wfds))
304     happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
306   if (FD_ISSET (fd, efds))
307     happened |= (POLLPRI | POLLRDBAND) & sought;
309   return happened;
311 #endif /* !MinGW */
313 int
314 poll (pfd, nfd, timeout)
315      struct pollfd *pfd;
316      nfds_t nfd;
317      int timeout;
319 #ifndef WIN32_NATIVE
320   fd_set rfds, wfds, efds;
321   struct timeval tv;
322   struct timeval *ptv;
323   int maxfd, rc;
324   nfds_t i;
326 # ifdef _SC_OPEN_MAX
327   static int sc_open_max = -1;
329   if (nfd < 0
330       || (nfd > sc_open_max
331           && (sc_open_max != -1
332               || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
333     {
334       errno = EINVAL;
335       return -1;
336     }
337 # else /* !_SC_OPEN_MAX */
338 #  ifdef OPEN_MAX
339   if (nfd < 0 || nfd > OPEN_MAX)
340     {
341       errno = EINVAL;
342       return -1;
343     }
344 #  endif /* OPEN_MAX -- else, no check is needed */
345 # endif /* !_SC_OPEN_MAX */
347   /* EFAULT is not necessary to implement, but let's do it in the
348      simplest case. */
349   if (!pfd)
350     {
351       errno = EFAULT;
352       return -1;
353     }
355   /* convert timeout number into a timeval structure */
356   if (timeout == 0)
357     {
358       ptv = &tv;
359       ptv->tv_sec = 0;
360       ptv->tv_usec = 0;
361     }
362   else if (timeout > 0)
363     {
364       ptv = &tv;
365       ptv->tv_sec = timeout / 1000;
366       ptv->tv_usec = (timeout % 1000) * 1000;
367     }
368   else if (timeout == INFTIM)
369     /* wait forever */
370     ptv = NULL;
371   else
372     {
373       errno = EINVAL;
374       return -1;
375     }
377   /* create fd sets and determine max fd */
378   maxfd = -1;
379   FD_ZERO (&rfds);
380   FD_ZERO (&wfds);
381   FD_ZERO (&efds);
382   for (i = 0; i < nfd; i++)
383     {
384       if (pfd[i].fd < 0)
385         continue;
387       if (pfd[i].events & (POLLIN | POLLRDNORM))
388         FD_SET (pfd[i].fd, &rfds);
390       /* see select(2): "the only exceptional condition detectable
391          is out-of-band data received on a socket", hence we push
392          POLLWRBAND events onto wfds instead of efds. */
393       if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
394         FD_SET (pfd[i].fd, &wfds);
395       if (pfd[i].events & (POLLPRI | POLLRDBAND))
396         FD_SET (pfd[i].fd, &efds);
397       if (pfd[i].fd >= maxfd
398           && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
399                                | POLLRDNORM | POLLRDBAND
400                                | POLLWRNORM | POLLWRBAND)))
401         {
402           maxfd = pfd[i].fd;
403           if (maxfd > FD_SETSIZE)
404             {
405               errno = EOVERFLOW;
406               return -1;
407             }
408         }
409     }
411   /* examine fd sets */
412   rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
413   if (rc < 0)
414     return rc;
416   /* establish results */
417   rc = 0;
418   for (i = 0; i < nfd; i++)
419     if (pfd[i].fd < 0)
420       pfd[i].revents = 0;
421     else
422       {
423         int happened = compute_revents (pfd[i].fd, pfd[i].events,
424                                         &rfds, &wfds, &efds);
425         if (happened)
426           {
427             pfd[i].revents = happened;
428             rc++;
429           }
430       }
432   return rc;
433 #else
434   static struct timeval tv0;
435   static HANDLE hEvent;
436   WSANETWORKEVENTS ev;
437   HANDLE h, handle_array[FD_SETSIZE + 2];
438   DWORD ret, wait_timeout, nhandles;
439   fd_set rfds, wfds, xfds;
440   BOOL poll_again;
441   MSG msg;
442   int rc = 0;
443   nfds_t i;
445   if (nfd < 0 || timeout < -1)
446     {
447       errno = EINVAL;
448       return -1;
449     }
451   if (!hEvent)
452     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
454   handle_array[0] = hEvent;
455   nhandles = 1;
456   FD_ZERO (&rfds);
457   FD_ZERO (&wfds);
458   FD_ZERO (&xfds);
460   /* Classify socket handles and create fd sets. */
461   for (i = 0; i < nfd; i++)
462     {
463       int sought = pfd[i].events;
464       pfd[i].revents = 0;
465       if (pfd[i].fd < 0)
466         continue;
467       if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
468                       | POLLPRI | POLLRDBAND)))
469         continue;
471       h = (HANDLE) _get_osfhandle (pfd[i].fd);
472       assert (h != NULL);
473       if (IsSocketHandle (h))
474         {
475           int requested = FD_CLOSE;
477           /* see above; socket handles are mapped onto select.  */
478           if (sought & (POLLIN | POLLRDNORM))
479             {
480               requested |= FD_READ | FD_ACCEPT;
481               FD_SET ((SOCKET) h, &rfds);
482             }
483           if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
484             {
485               requested |= FD_WRITE | FD_CONNECT;
486               FD_SET ((SOCKET) h, &wfds);
487             }
488           if (sought & (POLLPRI | POLLRDBAND))
489             {
490               requested |= FD_OOB;
491               FD_SET ((SOCKET) h, &xfds);
492             }
494           if (requested)
495             WSAEventSelect ((SOCKET) h, hEvent, requested);
496         }
497       else
498         {
499           /* Poll now.  If we get an event, do not poll again.  Also,
500              screen buffer handles are waitable, and they'll block until
501              a character is available.  win32_compute_revents eliminates
502              bits for the "wrong" direction. */
503           pfd[i].revents = win32_compute_revents (h, &sought);
504           if (sought)
505             handle_array[nhandles++] = h;
506           if (pfd[i].revents)
507             timeout = 0;
508         }
509     }
511   if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
512     {
513       /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
514          no need to call select again.  */
515       poll_again = FALSE;
516       wait_timeout = 0;
517     }
518   else
519     {
520       poll_again = TRUE;
521       if (timeout == INFTIM)
522         wait_timeout = INFINITE;
523       else
524         wait_timeout = timeout;
525     }
527   for (;;)
528     {
529       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
530                                        wait_timeout, QS_ALLINPUT);
532       if (ret == WAIT_OBJECT_0 + nhandles)
533         {
534           /* new input of some other kind */
535           BOOL bRet;
536           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
537             {
538               TranslateMessage (&msg);
539               DispatchMessage (&msg);
540             }
541         }
542       else
543         break;
544     }
546   if (poll_again)
547     select (0, &rfds, &wfds, &xfds, &tv0);
549   /* Place a sentinel at the end of the array.  */
550   handle_array[nhandles] = NULL;
551   nhandles = 1;
552   for (i = 0; i < nfd; i++)
553     {
554       int happened;
556       if (pfd[i].fd < 0)
557         continue;
558       if (!(pfd[i].events & (POLLIN | POLLRDNORM |
559                              POLLOUT | POLLWRNORM | POLLWRBAND)))
560         continue;
562       h = (HANDLE) _get_osfhandle (pfd[i].fd);
563       if (h != handle_array[nhandles])
564         {
565           /* It's a socket.  */
566           WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
567           WSAEventSelect ((SOCKET) h, 0, 0);
569           /* If we're lucky, WSAEnumNetworkEvents already provided a way
570              to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
571           if (FD_ISSET ((SOCKET) h, &rfds)
572               && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
573             ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
574           if (FD_ISSET ((SOCKET) h, &wfds))
575             ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
576           if (FD_ISSET ((SOCKET) h, &xfds))
577             ev.lNetworkEvents |= FD_OOB;
579           happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
580                                                    ev.lNetworkEvents);
581         }
582       else
583         {
584           /* Not a socket.  */
585           int sought = pfd[i].events;
586           happened = win32_compute_revents (h, &sought);
587           nhandles++;
588         }
590        if ((pfd[i].revents |= happened) != 0)
591         rc++;
592     }
594   return rc;
595 #endif