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