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>
72 /* BeOS does not have MSG_PEEK. */
86 /* Optimized test whether a HANDLE refers to a console.
87 See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
88 #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
91 IsSocketHandle (HANDLE h
)
95 if (IsConsoleHandle (h
))
98 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
99 WSAEnumNetworkEvents instead distinguishes the two correctly. */
100 ev
.lNetworkEvents
= 0xDEADBEEFl
;
101 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
102 return ev
.lNetworkEvents
!= 0xDEADBEEFl
;
106 HandleFromFd (int fd
)
108 /* since socket() returns a HANDLE already, try that first */
109 if (IsSocketHandle((HANDLE
) fd
))
110 return ((HANDLE
) fd
);
112 return ((HANDLE
) _get_osfhandle(fd
));
115 /* Declare data structures for ntdll functions. */
116 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
118 ULONG NamedPipeConfiguration
;
119 ULONG MaximumInstances
;
120 ULONG CurrentInstances
;
122 ULONG ReadDataAvailable
;
124 ULONG WriteQuotaAvailable
;
125 ULONG NamedPipeState
;
127 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
129 typedef struct _IO_STATUS_BLOCK
135 ULONG_PTR Information
;
136 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
138 typedef enum _FILE_INFORMATION_CLASS
{
139 FilePipeLocalInformation
= 24
140 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
142 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
143 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
146 # define PIPE_BUF 512
149 /* Compute revents values for file handle H. If some events cannot happen
150 for the handle, eliminate them from *P_SOUGHT. */
153 windows_compute_revents (HANDLE h
, int *p_sought
)
155 int i
, ret
, happened
;
156 INPUT_RECORD
*irbuffer
;
157 DWORD avail
, nbuffer
;
159 IO_STATUS_BLOCK iosb
;
160 FILE_PIPE_LOCAL_INFORMATION fpli
;
161 static PNtQueryInformationFile NtQueryInformationFile
;
162 static BOOL once_only
;
164 switch (GetFileType (h
))
169 NtQueryInformationFile
= (PNtQueryInformationFile
)
170 GetProcAddress (GetModuleHandle ("ntdll.dll"),
171 "NtQueryInformationFile");
176 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
179 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
181 else if (GetLastError () == ERROR_BROKEN_PIPE
)
186 /* It was the write-end of the pipe. Check if it is writable.
187 If NtQueryInformationFile fails, optimistically assume the pipe is
188 writable. This could happen on Windows 9x, where
189 NtQueryInformationFile is not available, or if we inherit a pipe
190 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
191 (I think this should not happen since Windows XP SP2; WINE seems
192 fine too). Otherwise, ensure that enough space is available for
194 memset (&iosb
, 0, sizeof (iosb
));
195 memset (&fpli
, 0, sizeof (fpli
));
197 if (!NtQueryInformationFile
198 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
199 FilePipeLocalInformation
)
200 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
201 || (fpli
.OutboundQuota
< PIPE_BUF
&&
202 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
203 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
208 ret
= WaitForSingleObject (h
, 0);
209 if (!IsConsoleHandle (h
))
210 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
213 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
217 *p_sought
&= POLLIN
| POLLRDNORM
;
223 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
224 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
225 if (!bRet
|| avail
== 0)
228 for (i
= 0; i
< avail
; i
++)
229 if (irbuffer
[i
].EventType
== KEY_EVENT
)
236 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
241 ret
= WaitForSingleObject (h
, 0);
242 if (ret
== WAIT_OBJECT_0
)
243 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
245 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
249 /* Convert fd_sets returned by select into revents values. */
252 windows_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
256 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
257 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
259 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
265 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
266 error
= WSAGetLastError ();
269 if (r
> 0 || error
== WSAENOTCONN
)
270 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
272 /* Distinguish hung-up sockets from other errors. */
273 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
274 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
281 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
282 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
284 if (lNetworkEvents
& FD_OOB
)
285 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
292 /* Convert select(2) returned fd_sets into poll(2) revents values. */
294 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
297 if (FD_ISSET (fd
, rfds
))
302 # if defined __MACH__ && defined __APPLE__
303 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
304 for some kinds of descriptors. Detect if this descriptor is a
305 connected socket, a server socket, or something else using a
306 0-byte recv, and use ioctl(2) to detect POLLHUP. */
307 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
308 socket_errno
= (r
< 0) ? errno
: 0;
309 if (r
== 0 || socket_errno
== ENOTSOCK
)
310 ioctl (fd
, FIONREAD
, &r
);
313 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
314 socket_errno
= (r
< 0) ? errno
: 0;
319 /* If the event happened on an unconnected server socket,
321 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
322 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
324 /* Distinguish hung-up sockets from other errors. */
325 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
326 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
329 /* some systems can't use recv() on non-socket, including HP NonStop */
330 else if (socket_errno
== ENOTSOCK
)
331 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
337 if (FD_ISSET (fd
, wfds
))
338 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
340 if (FD_ISSET (fd
, efds
))
341 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
348 pa_poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
352 #ifndef WINDOWS_NATIVE
353 fd_set rfds
, wfds
, efds
;
358 static int sc_open_max
= -1;
361 || (nfd
> sc_open_max
362 && (sc_open_max
!= -1
363 || nfd
> (sc_open_max
= sysconf (_SC_OPEN_MAX
)))))
368 # else /* !_SC_OPEN_MAX */
370 if (nfd
< 0 || nfd
> OPEN_MAX
)
375 # endif /* OPEN_MAX -- else, no check is needed */
376 # endif /* !_SC_OPEN_MAX */
377 #else /* WINDOWS_NATIVE*/
378 static HANDLE hEvent
;
380 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
381 DWORD ret
, wait_timeout
, nhandles
;
382 fd_set rfds
, wfds
, xfds
;
389 /* EFAULT is not necessary to implement, but let's do it in the
397 /* convert timeout number into a timeval structure */
404 else if (timeout
> 0)
407 ptv
->tv_sec
= timeout
/ 1000;
408 ptv
->tv_usec
= (timeout
% 1000) * 1000;
410 else if (timeout
== INFTIM
)
419 #ifndef WINDOWS_NATIVE
420 /* create fd sets and determine max fd */
425 for (i
= 0; i
< nfd
; i
++)
430 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
431 FD_SET (pfd
[i
].fd
, &rfds
);
433 /* see select(2): "the only exceptional condition detectable
434 is out-of-band data received on a socket", hence we push
435 POLLWRBAND events onto wfds instead of efds. */
436 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
437 FD_SET (pfd
[i
].fd
, &wfds
);
438 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
439 FD_SET (pfd
[i
].fd
, &efds
);
440 if (pfd
[i
].fd
>= maxfd
441 && (pfd
[i
].events
& (POLLIN
| POLLOUT
| POLLPRI
442 | POLLRDNORM
| POLLRDBAND
443 | POLLWRNORM
| POLLWRBAND
)))
446 if (maxfd
> FD_SETSIZE
)
454 /* examine fd sets */
455 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
459 /* establish results */
461 for (i
= 0; i
< nfd
; i
++)
466 int happened
= compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
467 &rfds
, &wfds
, &efds
);
470 pfd
[i
].revents
= happened
;
479 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
482 handle_array
[0] = hEvent
;
488 /* Classify socket handles and create fd sets. */
489 for (i
= 0; i
< nfd
; i
++)
491 int sought
= pfd
[i
].events
;
495 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
496 | POLLPRI
| POLLRDBAND
)))
499 h
= HandleFromFd (pfd
[i
].fd
);
500 assert (h
!= NULL
&& h
!= INVALID_HANDLE_VALUE
);
501 if (IsSocketHandle (h
))
503 int requested
= FD_CLOSE
;
505 /* see above; socket handles are mapped onto select. */
506 if (sought
& (POLLIN
| POLLRDNORM
))
508 requested
|= FD_READ
| FD_ACCEPT
;
509 FD_SET ((SOCKET
) h
, &rfds
);
511 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
513 requested
|= FD_WRITE
| FD_CONNECT
;
514 FD_SET ((SOCKET
) h
, &wfds
);
516 if (sought
& (POLLPRI
| POLLRDBAND
))
519 FD_SET ((SOCKET
) h
, &xfds
);
523 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
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
);
533 handle_array
[nhandles
++] = h
;
540 /* tune down to 0.25s. But don't touch smaller timeouts */
541 if (ptv
->tv_usec
> 250*1000 || ptv
->tv_sec
> 0)
542 ptv
->tv_usec
= 250*1000;
548 if (select (0, &rfds
, &wfds
, &xfds
, ptv
) > 0)
550 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
551 no need to call select again. */
558 if (timeout
== INFTIM
)
559 wait_timeout
= INFINITE
;
561 wait_timeout
= timeout
;
566 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
567 wait_timeout
, QS_ALLINPUT
);
569 if (ret
== WAIT_OBJECT_0
+ nhandles
)
571 /* new input of some other kind */
573 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
575 TranslateMessage (&msg
);
576 DispatchMessage (&msg
);
584 select (0, &rfds
, &wfds
, &xfds
, ptv
);
586 /* Place a sentinel at the end of the array. */
587 handle_array
[nhandles
] = NULL
;
589 for (i
= 0; i
< nfd
; i
++)
595 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
596 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
599 h
= (HANDLE
) HandleFromFd (pfd
[i
].fd
);
600 if (h
!= handle_array
[nhandles
])
603 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
604 WSAEventSelect ((SOCKET
) h
, 0, 0);
606 /* If we're lucky, WSAEnumNetworkEvents already provided a way
607 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
608 if (FD_ISSET ((SOCKET
) h
, &rfds
)
609 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
610 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
611 if (FD_ISSET ((SOCKET
) h
, &wfds
))
612 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
613 if (FD_ISSET ((SOCKET
) h
, &xfds
))
614 ev
.lNetworkEvents
|= FD_OOB
;
616 happened
= windows_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
622 int sought
= pfd
[i
].events
;
623 happened
= windows_compute_revents (h
, &sought
);
627 if ((pfd
[i
].revents
|= happened
) != 0)
631 if (!rc
&& timeout
== INFTIM
)