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