1
2 /* Emulation for poll(2)
3 Contributed by Paolo Bonzini.
4
5 Copyright 2001-2003, 2006-2012 Free Software Foundation, Inc.
6
7 This file is part of gnulib.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License along
20 with this program; if not, see <http://www.gnu.org/licenses/>. */
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 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #include <malloc.h>
31
32 #include <sys/types.h>
33
34 /* Specification. */
35 #include "poll.h"
36 typedef unsigned long nfds_t;
37
38 #include <errno.h>
39 #include <limits.h>
40 #include <assert.h>
41
42 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
43 # define WINDOWS_NATIVE
44 # include <winsock2.h>
45 # include <windows.h>
46 # include <io.h>
47 # include <stdio.h>
48 # include <conio.h>
49 # include <signal.h>
50 # if 0
51 # include "msvc-nothrow.h"
52 # endif
53 #else
54 # include <sys/time.h>
55 # include <sys/socket.h>
56 # include <sys/select.h>
57 # include <unistd.h>
58 #endif
59
60 #ifdef HAVE_SYS_IOCTL_H
61 # include <sys/ioctl.h>
62 #endif
63 #ifdef HAVE_SYS_FILIO_H
64 # include <sys/filio.h>
65 #endif
66
67 #include <time.h>
68
69 #include <pulsecore/core-util.h>
70
71 #ifndef INFTIM
72 # define INFTIM (-1)
73 #endif
74
75 /* BeOS does not have MSG_PEEK. */
76 #ifndef MSG_PEEK
77 # define MSG_PEEK 0
78 #endif
79
80 #ifndef POLLRDNORM
81 # define POLLRDNORM 0
82 # define POLLRDBAND 0
83 # define POLLWRNORM 0
84 # define POLLWRBAND 0
85 #endif
86
87 #ifdef WINDOWS_NATIVE
88
89 /* Optimized test whether a HANDLE refers to a console.
90 See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
91 #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
92
93 static BOOL
IsSocketHandle(HANDLE h)94 IsSocketHandle (HANDLE h)
95 {
96 WSANETWORKEVENTS ev;
97
98 if (IsConsoleHandle (h))
99 return FALSE;
100
101 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
102 WSAEnumNetworkEvents instead distinguishes the two correctly. */
103 ev.lNetworkEvents = 0xDEADBEEFl;
104 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
105 return ev.lNetworkEvents != 0xDEADBEEFl;
106 }
107
108 static HANDLE
HandleFromFd(int fd)109 HandleFromFd (int fd)
110 {
111 /* since socket() returns a HANDLE already, try that first */
112 if (IsSocketHandle(PA_INT_TO_PTR(fd)))
113 return PA_INT_TO_PTR(fd);
114
115 return ((HANDLE) _get_osfhandle(fd));
116 }
117
118 /* Declare data structures for ntdll functions. */
119 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
120 ULONG NamedPipeType;
121 ULONG NamedPipeConfiguration;
122 ULONG MaximumInstances;
123 ULONG CurrentInstances;
124 ULONG InboundQuota;
125 ULONG ReadDataAvailable;
126 ULONG OutboundQuota;
127 ULONG WriteQuotaAvailable;
128 ULONG NamedPipeState;
129 ULONG NamedPipeEnd;
130 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
131
132 typedef struct _IO_STATUS_BLOCK
133 {
134 union {
135 DWORD Status;
136 PVOID Pointer;
137 } u;
138 ULONG_PTR Information;
139 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
140
141 typedef enum _FILE_INFORMATION_CLASS {
142 FilePipeLocalInformation = 24
143 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
144
145 typedef DWORD (WINAPI *PNtQueryInformationFile)
146 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
147
148 # ifndef PIPE_BUF
149 # define PIPE_BUF 512
150 # endif
151
152 /* Compute revents values for file handle H. If some events cannot happen
153 for the handle, eliminate them from *P_SOUGHT. */
154
155 static int
windows_compute_revents(HANDLE h,int * p_sought)156 windows_compute_revents (HANDLE h, int *p_sought)
157 {
158 int i, ret, happened;
159 INPUT_RECORD *irbuffer;
160 DWORD avail, nbuffer;
161 BOOL bRet;
162 IO_STATUS_BLOCK iosb;
163 FILE_PIPE_LOCAL_INFORMATION fpli;
164 static PNtQueryInformationFile NtQueryInformationFile;
165 static BOOL once_only;
166
167 switch (GetFileType (h))
168 {
169 case FILE_TYPE_PIPE:
170 if (!once_only)
171 {
172 NtQueryInformationFile = (PNtQueryInformationFile)
173 GetProcAddress (GetModuleHandle ("ntdll.dll"),
174 "NtQueryInformationFile");
175 once_only = TRUE;
176 }
177
178 happened = 0;
179 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
180 {
181 if (avail)
182 happened |= *p_sought & (POLLIN | POLLRDNORM);
183 }
184 else if (GetLastError () == ERROR_BROKEN_PIPE)
185 happened |= POLLHUP;
186
187 else
188 {
189 /* It was the write-end of the pipe. Check if it is writable.
190 If NtQueryInformationFile fails, optimistically assume the pipe is
191 writable. This could happen on Windows 9x, where
192 NtQueryInformationFile is not available, or if we inherit a pipe
193 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
194 (I think this should not happen since Windows XP SP2; WINE seems
195 fine too). Otherwise, ensure that enough space is available for
196 atomic writes. */
197 memset (&iosb, 0, sizeof (iosb));
198 memset (&fpli, 0, sizeof (fpli));
199
200 if (!NtQueryInformationFile
201 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
202 FilePipeLocalInformation)
203 || fpli.WriteQuotaAvailable >= PIPE_BUF
204 || (fpli.OutboundQuota < PIPE_BUF &&
205 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
206 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
207 }
208 return happened;
209
210 case FILE_TYPE_CHAR:
211 ret = WaitForSingleObject (h, 0);
212 if (!IsConsoleHandle (h))
213 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
214
215 nbuffer = avail = 0;
216 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
217 if (bRet)
218 {
219 /* Input buffer. */
220 *p_sought &= POLLIN | POLLRDNORM;
221 if (nbuffer == 0)
222 return POLLHUP;
223 if (!*p_sought)
224 return 0;
225
226 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
227 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
228 if (!bRet || avail == 0)
229 return POLLHUP;
230
231 for (i = 0; i < avail; i++)
232 if (irbuffer[i].EventType == KEY_EVENT)
233 return *p_sought;
234 return 0;
235 }
236 else
237 {
238 /* Screen buffer. */
239 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
240 return *p_sought;
241 }
242
243 default:
244 ret = WaitForSingleObject (h, 0);
245 if (ret == WAIT_OBJECT_0)
246 return *p_sought & ~(POLLPRI | POLLRDBAND);
247
248 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
249 }
250 }
251
252 /* Convert fd_sets returned by select into revents values. */
253
254 static int
windows_compute_revents_socket(SOCKET h,int sought,long lNetworkEvents)255 windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
256 {
257 int happened = 0;
258
259 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
260 happened |= (POLLIN | POLLRDNORM) & sought;
261
262 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
263 {
264 int r, error;
265
266 char data[64];
267 WSASetLastError (0);
268 r = recv (h, data, sizeof (data), MSG_PEEK);
269 error = WSAGetLastError ();
270 WSASetLastError (0);
271
272 if (r > 0 || error == WSAENOTCONN)
273 happened |= (POLLIN | POLLRDNORM) & sought;
274
275 /* Distinguish hung-up sockets from other errors. */
276 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
277 || error == WSAECONNABORTED || error == WSAENETRESET)
278 happened |= POLLHUP;
279
280 else
281 happened |= POLLERR;
282 }
283
284 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
285 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
286
287 if (lNetworkEvents & FD_OOB)
288 happened |= (POLLPRI | POLLRDBAND) & sought;
289
290 return happened;
291 }
292
293 #else /* !MinGW */
294
295 /* Convert select(2) returned fd_sets into poll(2) revents values. */
296 static int
compute_revents(int fd,int sought,fd_set * rfds,fd_set * wfds,fd_set * efds)297 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
298 {
299 int happened = 0;
300 if (FD_ISSET (fd, rfds))
301 {
302 int r;
303 int socket_errno;
304
305 # if defined __MACH__ && defined __APPLE__
306 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
307 for some kinds of descriptors. Detect if this descriptor is a
308 connected socket, a server socket, or something else using a
309 0-byte recv, and use ioctl(2) to detect POLLHUP. */
310 r = recv (fd, NULL, 0, MSG_PEEK);
311 socket_errno = (r < 0) ? errno : 0;
312 if (r == 0 || socket_errno == ENOTSOCK)
313 ioctl (fd, FIONREAD, &r);
314 # else
315 char data[64];
316 r = recv (fd, data, sizeof (data), MSG_PEEK);
317 socket_errno = (r < 0) ? errno : 0;
318 # endif
319 if (r == 0)
320 happened |= POLLHUP;
321
322 /* If the event happened on an unconnected server socket,
323 that's fine. */
324 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
325 happened |= (POLLIN | POLLRDNORM) & sought;
326
327 /* Distinguish hung-up sockets from other errors. */
328 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
329 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
330 happened |= POLLHUP;
331
332 /* some systems can't use recv() on non-socket, including HP NonStop */
333 else if (socket_errno == ENOTSOCK)
334 happened |= (POLLIN | POLLRDNORM) & sought;
335
336 else
337 happened |= POLLERR;
338 }
339
340 if (FD_ISSET (fd, wfds))
341 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
342
343 if (FD_ISSET (fd, efds))
344 happened |= (POLLPRI | POLLRDBAND) & sought;
345
346 return happened;
347 }
348 #endif /* !MinGW */
349
350 int
pa_poll(struct pollfd * pfd,nfds_t nfd,int timeout)351 pa_poll (struct pollfd *pfd, nfds_t nfd, int timeout)
352 {
353 struct timeval tv;
354
355 #ifndef WINDOWS_NATIVE
356 struct timeval *ptv;
357 fd_set rfds, wfds, efds;
358 int maxfd, rc;
359 nfds_t i;
360
361 # ifdef _SC_OPEN_MAX
362 static int sc_open_max = -1;
363
364 if (nfd < 0
365 || (nfd > sc_open_max
366 && (sc_open_max != -1
367 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
368 {
369 errno = EINVAL;
370 return -1;
371 }
372 # else /* !_SC_OPEN_MAX */
373 # ifdef OPEN_MAX
374 if (nfd < 0 || nfd > OPEN_MAX)
375 {
376 errno = EINVAL;
377 return -1;
378 }
379 # endif /* OPEN_MAX -- else, no check is needed */
380 # endif /* !_SC_OPEN_MAX */
381
382 /* EFAULT is not necessary to implement, but let's do it in the
383 simplest case. */
384 if (!pfd && nfd)
385 {
386 errno = EFAULT;
387 return -1;
388 }
389
390 /* convert timeout number into a timeval structure */
391 if (timeout == 0)
392 {
393 ptv = &tv;
394 ptv->tv_sec = 0;
395 ptv->tv_usec = 0;
396 }
397 else if (timeout > 0)
398 {
399 ptv = &tv;
400 ptv->tv_sec = timeout / 1000;
401 ptv->tv_usec = (timeout % 1000) * 1000;
402 }
403 else if (timeout == INFTIM)
404 /* wait forever */
405 ptv = NULL;
406 else
407 {
408 errno = EINVAL;
409 return -1;
410 }
411
412 /* create fd sets and determine max fd */
413 maxfd = -1;
414 FD_ZERO (&rfds);
415 FD_ZERO (&wfds);
416 FD_ZERO (&efds);
417 for (i = 0; i < nfd; i++)
418 {
419 if (pfd[i].fd < 0)
420 continue;
421
422 if (pfd[i].events & (POLLIN | POLLRDNORM))
423 FD_SET (pfd[i].fd, &rfds);
424
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);
432 if (pfd[i].fd >= maxfd
433 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
434 | POLLRDNORM | POLLRDBAND
435 | POLLWRNORM | POLLWRBAND)))
436 {
437 maxfd = pfd[i].fd;
438 if (maxfd > FD_SETSIZE)
439 {
440 errno = EOVERFLOW;
441 return -1;
442 }
443 }
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 if (pfd[i].fd < 0)
455 pfd[i].revents = 0;
456 else
457 {
458 int happened = compute_revents (pfd[i].fd, pfd[i].events,
459 &rfds, &wfds, &efds);
460 if (happened)
461 {
462 pfd[i].revents = happened;
463 rc++;
464 }
465 }
466
467 return rc;
468 #else /* WINDOWS_NATIVE*/
469 HANDLE hEvent;
470 WSANETWORKEVENTS ev;
471 HANDLE h, handle_array[FD_SETSIZE + 2];
472 DWORD ret, wait_timeout, nhandles;
473 fd_set rfds, wfds, xfds;
474 BOOL poll_again;
475 MSG msg;
476 int rc = 0;
477 nfds_t i;
478
479 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
480
481 restart:
482 handle_array[0] = hEvent;
483 nhandles = 1;
484 FD_ZERO (&rfds);
485 FD_ZERO (&wfds);
486 FD_ZERO (&xfds);
487
488 /* Classify socket handles and create fd sets. */
489 for (i = 0; i < nfd; i++)
490 {
491 int sought = pfd[i].events;
492 pfd[i].revents = 0;
493 if (pfd[i].fd < 0)
494 continue;
495 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
496 | POLLPRI | POLLRDBAND)))
497 continue;
498
499 h = HandleFromFd (pfd[i].fd);
500 assert (h != NULL && h != INVALID_HANDLE_VALUE);
501 if (IsSocketHandle (h))
502 {
503 int requested = FD_CLOSE;
504
505 /* see above; socket handles are mapped onto select. */
506 if (sought & (POLLIN | POLLRDNORM))
507 {
508 requested |= FD_READ | FD_ACCEPT;
509 FD_SET ((SOCKET) h, &rfds);
510 }
511 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
512 {
513 requested |= FD_WRITE | FD_CONNECT;
514 FD_SET ((SOCKET) h, &wfds);
515 }
516 if (sought & (POLLPRI | POLLRDBAND))
517 {
518 requested |= FD_OOB;
519 FD_SET ((SOCKET) h, &xfds);
520 }
521
522 if (requested)
523 WSAEventSelect ((SOCKET) h, hEvent, requested);
524 }
525 else
526 {
527 /* Poll now. If we get an event, do not poll again. Also,
528 screen buffer handles are waitable, and they'll block until
529 a character is available. windows_compute_revents eliminates
530 bits for the "wrong" direction. */
531 pfd[i].revents = windows_compute_revents (h, &sought);
532 if (sought)
533 handle_array[nhandles++] = h;
534 if (pfd[i].revents)
535 timeout = 0;
536 }
537 }
538
539 /* We poll current status using select(). It cannot be used to check
540 anything but sockets, so we still have to wait in
541 MsgWaitForMultipleObjects(). But that in turn cannot check existing
542 state, so we can't remove this select(). */
543 /* FIXME: MSDN states that we cannot give empty fd_set:s. */
544 tv.tv_sec = tv.tv_usec = 0;
545 if (select (0, &rfds, &wfds, &xfds, &tv) > 0)
546 {
547 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
548 no need to call select again. */
549 poll_again = FALSE;
550 wait_timeout = 0;
551 }
552 else
553 {
554 poll_again = TRUE;
555 if (timeout == INFTIM)
556 wait_timeout = INFINITE;
557 else
558 wait_timeout = timeout;
559 }
560
561 for (;;)
562 {
563 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
564 wait_timeout, QS_ALLINPUT);
565
566 if (ret == WAIT_OBJECT_0 + nhandles)
567 {
568 /* new input of some other kind */
569 BOOL bRet;
570 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
571 {
572 if (msg.message == WM_QUIT)
573 raise(SIGTERM);
574 else
575 {
576 TranslateMessage (&msg);
577 DispatchMessage (&msg);
578 }
579 }
580 }
581 else
582 break;
583 }
584
585 if (poll_again)
586 select (0, &rfds, &wfds, &xfds, &tv);
587
588 /* Place a sentinel at the end of the array. */
589 handle_array[nhandles] = NULL;
590 nhandles = 1;
591 for (i = 0; i < nfd; i++)
592 {
593 int happened;
594
595 if (pfd[i].fd < 0)
596 continue;
597 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
598 POLLOUT | POLLWRNORM | POLLWRBAND)))
599 continue;
600
601 h = (HANDLE) HandleFromFd (pfd[i].fd);
602 if (h != handle_array[nhandles])
603 {
604 /* It's a socket. */
605 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
606 WSAEventSelect ((SOCKET) h, 0, 0);
607 /* Have to restore blocking as WSAEventSelect() clears it */
608 if (!pa_is_fd_nonblock(pfd[i].fd))
609 pa_make_fd_block(pfd[i].fd);
610
611 /* If we're lucky, WSAEnumNetworkEvents already provided a way
612 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
613 if (FD_ISSET ((SOCKET) h, &rfds)
614 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
615 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
616 if (FD_ISSET ((SOCKET) h, &wfds))
617 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
618 if (FD_ISSET ((SOCKET) h, &xfds))
619 ev.lNetworkEvents |= FD_OOB;
620
621 happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
622 ev.lNetworkEvents);
623 }
624 else
625 {
626 /* Not a socket. */
627 int sought = pfd[i].events;
628 happened = windows_compute_revents (h, &sought);
629 nhandles++;
630 }
631
632 if ((pfd[i].revents |= happened) != 0)
633 rc++;
634 }
635
636 if (!rc && timeout == INFTIM)
637 {
638 SleepEx (1, TRUE);
639 goto restart;
640 }
641
642 CloseHandle(hEvent);
643
644 return rc;
645 #endif
646 }
647