2 /* Emulation for poll(2)
3 Contributed by Paolo Bonzini.
5 Copyright 2001-2003, 2006-2012 Free Software Foundation, Inc.
7 This file is part of gnulib.
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)
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.
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/>. */
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"
32 #include <sys/types.h>
36 typedef unsigned long nfds_t
;
42 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
43 # define WINDOWS_NATIVE
44 # include <winsock2.h>
50 # include "msvc-nothrow.h"
53 # include <sys/time.h>
54 # include <sys/socket.h>
55 # include <sys/select.h>
59 #ifdef HAVE_SYS_IOCTL_H
60 # include <sys/ioctl.h>
62 #ifdef HAVE_SYS_FILIO_H
63 # include <sys/filio.h>
68 #include <pulsecore/core-util.h>
74 /* BeOS does not have MSG_PEEK. */
88 /* Optimized test whether a HANDLE refers to a console.
89 See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
90 #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
93 IsSocketHandle (HANDLE h
)
97 if (IsConsoleHandle (h
))
100 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
101 WSAEnumNetworkEvents instead distinguishes the two correctly. */
102 ev
.lNetworkEvents
= 0xDEADBEEFl
;
103 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
104 return ev
.lNetworkEvents
!= 0xDEADBEEFl
;
108 HandleFromFd (int fd
)
110 /* since socket() returns a HANDLE already, try that first */
111 if (IsSocketHandle((HANDLE
) fd
))
112 return ((HANDLE
) fd
);
114 return ((HANDLE
) _get_osfhandle(fd
));
117 /* Declare data structures for ntdll functions. */
118 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
120 ULONG NamedPipeConfiguration
;
121 ULONG MaximumInstances
;
122 ULONG CurrentInstances
;
124 ULONG ReadDataAvailable
;
126 ULONG WriteQuotaAvailable
;
127 ULONG NamedPipeState
;
129 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
131 typedef struct _IO_STATUS_BLOCK
137 ULONG_PTR Information
;
138 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
140 typedef enum _FILE_INFORMATION_CLASS
{
141 FilePipeLocalInformation
= 24
142 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
144 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
145 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
148 # define PIPE_BUF 512
151 /* Compute revents values for file handle H. If some events cannot happen
152 for the handle, eliminate them from *P_SOUGHT. */
155 windows_compute_revents (HANDLE h
, int *p_sought
)
157 int i
, ret
, happened
;
158 INPUT_RECORD
*irbuffer
;
159 DWORD avail
, nbuffer
;
161 IO_STATUS_BLOCK iosb
;
162 FILE_PIPE_LOCAL_INFORMATION fpli
;
163 static PNtQueryInformationFile NtQueryInformationFile
;
164 static BOOL once_only
;
166 switch (GetFileType (h
))
171 NtQueryInformationFile
= (PNtQueryInformationFile
)
172 GetProcAddress (GetModuleHandle ("ntdll.dll"),
173 "NtQueryInformationFile");
178 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
181 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
183 else if (GetLastError () == ERROR_BROKEN_PIPE
)
188 /* It was the write-end of the pipe. Check if it is writable.
189 If NtQueryInformationFile fails, optimistically assume the pipe is
190 writable. This could happen on Windows 9x, where
191 NtQueryInformationFile is not available, or if we inherit a pipe
192 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
193 (I think this should not happen since Windows XP SP2; WINE seems
194 fine too). Otherwise, ensure that enough space is available for
196 memset (&iosb
, 0, sizeof (iosb
));
197 memset (&fpli
, 0, sizeof (fpli
));
199 if (!NtQueryInformationFile
200 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
201 FilePipeLocalInformation
)
202 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
203 || (fpli
.OutboundQuota
< PIPE_BUF
&&
204 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
205 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
210 ret
= WaitForSingleObject (h
, 0);
211 if (!IsConsoleHandle (h
))
212 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
215 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
219 *p_sought
&= POLLIN
| POLLRDNORM
;
225 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
226 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
227 if (!bRet
|| avail
== 0)
230 for (i
= 0; i
< avail
; i
++)
231 if (irbuffer
[i
].EventType
== KEY_EVENT
)
238 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
243 ret
= WaitForSingleObject (h
, 0);
244 if (ret
== WAIT_OBJECT_0
)
245 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
247 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
251 /* Convert fd_sets returned by select into revents values. */
254 windows_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
258 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
259 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
261 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
267 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
268 error
= WSAGetLastError ();
271 if (r
> 0 || error
== WSAENOTCONN
)
272 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
274 /* Distinguish hung-up sockets from other errors. */
275 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
276 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
283 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
284 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
286 if (lNetworkEvents
& FD_OOB
)
287 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
294 /* Convert select(2) returned fd_sets into poll(2) revents values. */
296 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
299 if (FD_ISSET (fd
, rfds
))
304 # if defined __MACH__ && defined __APPLE__
305 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
306 for some kinds of descriptors. Detect if this descriptor is a
307 connected socket, a server socket, or something else using a
308 0-byte recv, and use ioctl(2) to detect POLLHUP. */
309 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
310 socket_errno
= (r
< 0) ? errno
: 0;
311 if (r
== 0 || socket_errno
== ENOTSOCK
)
312 ioctl (fd
, FIONREAD
, &r
);
315 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
316 socket_errno
= (r
< 0) ? errno
: 0;
321 /* If the event happened on an unconnected server socket,
323 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
324 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
326 /* Distinguish hung-up sockets from other errors. */
327 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
328 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
331 /* some systems can't use recv() on non-socket, including HP NonStop */
332 else if (socket_errno
== ENOTSOCK
)
333 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
339 if (FD_ISSET (fd
, wfds
))
340 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
342 if (FD_ISSET (fd
, efds
))
343 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
350 pa_poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
354 #ifndef WINDOWS_NATIVE
355 fd_set rfds
, wfds
, efds
;
360 static int sc_open_max
= -1;
363 || (nfd
> sc_open_max
364 && (sc_open_max
!= -1
365 || nfd
> (sc_open_max
= sysconf (_SC_OPEN_MAX
)))))
370 # else /* !_SC_OPEN_MAX */
372 if (nfd
< 0 || nfd
> OPEN_MAX
)
377 # endif /* OPEN_MAX -- else, no check is needed */
378 # endif /* !_SC_OPEN_MAX */
379 #else /* WINDOWS_NATIVE*/
380 static HANDLE hEvent
;
382 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
383 DWORD ret
, wait_timeout
, nhandles
;
384 fd_set rfds
, wfds
, xfds
;
391 /* EFAULT is not necessary to implement, but let's do it in the
399 /* convert timeout number into a timeval structure */
406 else if (timeout
> 0)
409 ptv
->tv_sec
= timeout
/ 1000;
410 ptv
->tv_usec
= (timeout
% 1000) * 1000;
412 else if (timeout
== INFTIM
)
421 #ifndef WINDOWS_NATIVE
422 /* create fd sets and determine max fd */
427 for (i
= 0; i
< nfd
; i
++)
432 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
433 FD_SET (pfd
[i
].fd
, &rfds
);
435 /* see select(2): "the only exceptional condition detectable
436 is out-of-band data received on a socket", hence we push
437 POLLWRBAND events onto wfds instead of efds. */
438 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
439 FD_SET (pfd
[i
].fd
, &wfds
);
440 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
441 FD_SET (pfd
[i
].fd
, &efds
);
442 if (pfd
[i
].fd
>= maxfd
443 && (pfd
[i
].events
& (POLLIN
| POLLOUT
| POLLPRI
444 | POLLRDNORM
| POLLRDBAND
445 | POLLWRNORM
| POLLWRBAND
)))
448 if (maxfd
> FD_SETSIZE
)
456 /* examine fd sets */
457 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
461 /* establish results */
463 for (i
= 0; i
< nfd
; i
++)
468 int happened
= compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
469 &rfds
, &wfds
, &efds
);
472 pfd
[i
].revents
= happened
;
481 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
484 handle_array
[0] = hEvent
;
490 /* Classify socket handles and create fd sets. */
491 for (i
= 0; i
< nfd
; i
++)
493 int sought
= pfd
[i
].events
;
497 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
498 | POLLPRI
| POLLRDBAND
)))
501 h
= HandleFromFd (pfd
[i
].fd
);
502 assert (h
!= NULL
&& h
!= INVALID_HANDLE_VALUE
);
503 if (IsSocketHandle (h
))
505 int requested
= FD_CLOSE
;
507 /* see above; socket handles are mapped onto select. */
508 if (sought
& (POLLIN
| POLLRDNORM
))
510 requested
|= FD_READ
| FD_ACCEPT
;
511 FD_SET ((SOCKET
) h
, &rfds
);
513 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
515 requested
|= FD_WRITE
| FD_CONNECT
;
516 FD_SET ((SOCKET
) h
, &wfds
);
518 if (sought
& (POLLPRI
| POLLRDBAND
))
521 FD_SET ((SOCKET
) h
, &xfds
);
525 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
529 /* Poll now. If we get an event, do not poll again. Also,
530 screen buffer handles are waitable, and they'll block until
531 a character is available. windows_compute_revents eliminates
532 bits for the "wrong" direction. */
533 pfd
[i
].revents
= windows_compute_revents (h
, &sought
);
535 handle_array
[nhandles
++] = h
;
542 /* tune down to 0.25s. But don't touch smaller timeouts */
543 if (ptv
->tv_usec
> 250*1000 || ptv
->tv_sec
> 0)
544 ptv
->tv_usec
= 250*1000;
550 if (select (0, &rfds
, &wfds
, &xfds
, ptv
) > 0)
552 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
553 no need to call select again. */
560 if (timeout
== INFTIM
)
561 wait_timeout
= INFINITE
;
563 wait_timeout
= timeout
;
568 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
569 wait_timeout
, QS_ALLINPUT
);
571 if (ret
== WAIT_OBJECT_0
+ nhandles
)
573 /* new input of some other kind */
575 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
577 TranslateMessage (&msg
);
578 DispatchMessage (&msg
);
586 select (0, &rfds
, &wfds
, &xfds
, ptv
);
588 /* Place a sentinel at the end of the array. */
589 handle_array
[nhandles
] = NULL
;
591 for (i
= 0; i
< nfd
; i
++)
597 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
598 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
601 h
= (HANDLE
) HandleFromFd (pfd
[i
].fd
);
602 if (h
!= handle_array
[nhandles
])
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
);
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
;
621 happened
= windows_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
627 int sought
= pfd
[i
].events
;
628 happened
= windows_compute_revents (h
, &sought
);
632 if ((pfd
[i
].revents
|= happened
) != 0)
636 if (!rc
&& timeout
== INFTIM
)