1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
6 This file is part of gnulib.
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)
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.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, see <http://www.gnu.org/licenses/>. */
21 /* Tell gcc not to warn about the (nfd < 0) tests, below. */
22 #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
23 # pragma GCC diagnostic ignored "-Wtype-limits"
30 #include <sys/types.h>
36 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
38 # if defined (_MSC_VER) && !defined(_WIN32_WINNT)
39 # define _WIN32_WINNT 0x0502
41 # include <winsock2.h>
47 # include <sys/time.h>
48 # include <sys/socket.h>
49 # ifndef NO_SYS_SELECT_H
50 # include <sys/select.h>
58 #ifdef HAVE_SYS_IOCTL_H
59 # include <sys/ioctl.h>
61 #ifdef HAVE_SYS_FILIO_H
62 # include <sys/filio.h>
71 /* BeOS does not have MSG_PEEK. */
78 #define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
81 IsSocketHandle (HANDLE h
)
85 if (IsConsoleHandle (h
))
88 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
89 WSAEnumNetworkEvents instead distinguishes the two correctly. */
90 ev
.lNetworkEvents
= 0xDEADBEEF;
91 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
92 return ev
.lNetworkEvents
!= 0xDEADBEEF;
95 /* Declare data structures for ntdll functions. */
96 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
98 ULONG NamedPipeConfiguration
;
99 ULONG MaximumInstances
;
100 ULONG CurrentInstances
;
102 ULONG ReadDataAvailable
;
104 ULONG WriteQuotaAvailable
;
105 ULONG NamedPipeState
;
107 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
109 typedef struct _IO_STATUS_BLOCK
115 ULONG_PTR Information
;
116 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
118 typedef enum _FILE_INFORMATION_CLASS
{
119 FilePipeLocalInformation
= 24
120 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
122 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
123 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
126 # define PIPE_BUF 512
129 /* Compute revents values for file handle H. If some events cannot happen
130 for the handle, eliminate them from *P_SOUGHT. */
133 win32_compute_revents (HANDLE h
, int *p_sought
)
135 int i
, ret
, happened
;
136 INPUT_RECORD
*irbuffer
;
137 DWORD avail
, nbuffer
;
139 IO_STATUS_BLOCK iosb
;
140 FILE_PIPE_LOCAL_INFORMATION fpli
;
141 static PNtQueryInformationFile NtQueryInformationFile
;
142 static BOOL once_only
;
144 switch (GetFileType (h
))
149 NtQueryInformationFile
= (PNtQueryInformationFile
)
150 GetProcAddress (GetModuleHandle ("ntdll.dll"),
151 "NtQueryInformationFile");
156 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
159 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
161 else if (GetLastError () == ERROR_BROKEN_PIPE
)
166 /* It was the write-end of the pipe. Check if it is writable.
167 If NtQueryInformationFile fails, optimistically assume the pipe is
168 writable. This could happen on Win9x, where NtQueryInformationFile
169 is not available, or if we inherit a pipe that doesn't permit
170 FILE_READ_ATTRIBUTES access on the write end (I think this should
171 not happen since WinXP SP2; WINE seems fine too). Otherwise,
172 ensure that enough space is available for atomic writes. */
173 memset (&iosb
, 0, sizeof (iosb
));
174 memset (&fpli
, 0, sizeof (fpli
));
176 if (!NtQueryInformationFile
177 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
178 FilePipeLocalInformation
)
179 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
180 || (fpli
.OutboundQuota
< PIPE_BUF
&&
181 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
182 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
187 ret
= WaitForSingleObject (h
, 0);
188 if (!IsConsoleHandle (h
))
189 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
192 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
196 *p_sought
&= POLLIN
| POLLRDNORM
;
202 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
203 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
204 if (!bRet
|| avail
== 0)
207 for (i
= 0; i
< avail
; i
++)
208 if (irbuffer
[i
].EventType
== KEY_EVENT
)
215 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
220 ret
= WaitForSingleObject (h
, 0);
221 if (ret
== WAIT_OBJECT_0
)
222 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
224 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
228 /* Convert fd_sets returned by select into revents values. */
231 win32_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
235 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
236 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
238 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
244 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
245 error
= WSAGetLastError ();
248 if (r
> 0 || error
== WSAENOTCONN
)
249 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
251 /* Distinguish hung-up sockets from other errors. */
252 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
253 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
260 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
261 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
263 if (lNetworkEvents
& FD_OOB
)
264 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
271 /* Convert select(2) returned fd_sets into poll(2) revents values. */
273 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
276 if (FD_ISSET (fd
, rfds
))
281 # if defined __MACH__ && defined __APPLE__
282 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
283 for some kinds of descriptors. Detect if this descriptor is a
284 connected socket, a server socket, or something else using a
285 0-byte recv, and use ioctl(2) to detect POLLHUP. */
286 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
287 socket_errno
= (r
< 0) ? errno
: 0;
288 if (r
== 0 || socket_errno
== ENOTSOCK
)
289 ioctl (fd
, FIONREAD
, &r
);
292 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
293 socket_errno
= (r
< 0) ? errno
: 0;
298 /* If the event happened on an unconnected server socket,
300 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
301 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
303 /* Distinguish hung-up sockets from other errors. */
304 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
305 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
308 /* some systems can't use recv() on non-socket, including HP NonStop */
309 else if (/* (r == -1) && */ socket_errno
== ENOTSOCK
)
310 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
316 if (FD_ISSET (fd
, wfds
))
317 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
319 if (FD_ISSET (fd
, efds
))
320 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
327 poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
330 fd_set rfds
, wfds
, efds
;
337 static int sc_open_max
= -1;
340 || (nfd
> sc_open_max
341 && (sc_open_max
!= -1
342 || nfd
> (sc_open_max
= sysconf (_SC_OPEN_MAX
)))))
347 # else /* !_SC_OPEN_MAX */
349 if (nfd
< 0 || nfd
> OPEN_MAX
)
354 # endif /* OPEN_MAX -- else, no check is needed */
355 # endif /* !_SC_OPEN_MAX */
357 /* EFAULT is not necessary to implement, but let's do it in the
365 /* convert timeout number into a timeval structure */
372 else if (timeout
> 0)
375 ptv
->tv_sec
= timeout
/ 1000;
376 ptv
->tv_usec
= (timeout
% 1000) * 1000;
378 else if (timeout
== INFTIM
)
387 /* create fd sets and determine max fd */
392 for (i
= 0; i
< nfd
; i
++)
397 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
398 FD_SET (pfd
[i
].fd
, &rfds
);
400 /* see select(2): "the only exceptional condition detectable
401 is out-of-band data received on a socket", hence we push
402 POLLWRBAND events onto wfds instead of efds. */
403 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
404 FD_SET (pfd
[i
].fd
, &wfds
);
405 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
406 FD_SET (pfd
[i
].fd
, &efds
);
407 if (pfd
[i
].fd
>= maxfd
408 && (pfd
[i
].events
& (POLLIN
| POLLOUT
| POLLPRI
409 | POLLRDNORM
| POLLRDBAND
410 | POLLWRNORM
| POLLWRBAND
)))
413 if (maxfd
> FD_SETSIZE
)
421 /* examine fd sets */
422 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
426 /* establish results */
428 for (i
= 0; i
< nfd
; i
++)
433 int happened
= compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
434 &rfds
, &wfds
, &efds
);
437 pfd
[i
].revents
= happened
;
448 static struct timeval tv0
;
449 static HANDLE hEvent
;
451 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
452 DWORD ret
, wait_timeout
, nhandles
, start
= 0, elapsed
, orig_timeout
= 0;
453 fd_set rfds
, wfds
, xfds
;
459 if (nfd
< 0 || timeout
< -1)
465 if (timeout
!= INFTIM
)
467 orig_timeout
= timeout
;
468 start
= GetTickCount();
472 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
475 handle_array
[0] = hEvent
;
481 /* Classify socket handles and create fd sets. */
482 for (i
= 0; i
< nfd
; i
++)
484 int sought
= pfd
[i
].events
;
488 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
489 | POLLPRI
| POLLRDBAND
)))
492 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
494 if (IsSocketHandle (h
))
496 int requested
= FD_CLOSE
;
498 /* see above; socket handles are mapped onto select. */
499 if (sought
& (POLLIN
| POLLRDNORM
))
501 requested
|= FD_READ
| FD_ACCEPT
;
502 FD_SET ((SOCKET
) h
, &rfds
);
504 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
506 requested
|= FD_WRITE
| FD_CONNECT
;
507 FD_SET ((SOCKET
) h
, &wfds
);
509 if (sought
& (POLLPRI
| POLLRDBAND
))
512 FD_SET ((SOCKET
) h
, &xfds
);
516 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
520 /* Poll now. If we get an event, do not poll again. Also,
521 screen buffer handles are waitable, and they'll block until
522 a character is available. win32_compute_revents eliminates
523 bits for the "wrong" direction. */
524 pfd
[i
].revents
= win32_compute_revents (h
, &sought
);
526 handle_array
[nhandles
++] = h
;
532 if (select (0, &rfds
, &wfds
, &xfds
, &tv0
) > 0)
534 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
535 no need to call select again. */
542 if (timeout
== INFTIM
)
543 wait_timeout
= INFINITE
;
545 wait_timeout
= timeout
;
550 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
551 wait_timeout
, QS_ALLINPUT
);
553 if (ret
== WAIT_OBJECT_0
+ nhandles
)
555 /* new input of some other kind */
557 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
559 TranslateMessage (&msg
);
560 DispatchMessage (&msg
);
568 select (0, &rfds
, &wfds
, &xfds
, &tv0
);
570 /* Place a sentinel at the end of the array. */
571 handle_array
[nhandles
] = NULL
;
573 for (i
= 0; i
< nfd
; i
++)
579 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
580 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
583 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
584 if (h
!= handle_array
[nhandles
])
587 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
588 WSAEventSelect ((SOCKET
) h
, NULL
, 0);
590 /* If we're lucky, WSAEnumNetworkEvents already provided a way
591 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
592 if (FD_ISSET ((SOCKET
) h
, &rfds
)
593 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
594 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
595 if (FD_ISSET ((SOCKET
) h
, &wfds
))
596 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
597 if (FD_ISSET ((SOCKET
) h
, &xfds
))
598 ev
.lNetworkEvents
|= FD_OOB
;
600 happened
= win32_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
606 int sought
= pfd
[i
].events
;
607 happened
= win32_compute_revents (h
, &sought
);
611 if ((pfd
[i
].revents
|= happened
) != 0)
615 if (!rc
&& orig_timeout
&& timeout
!= INFTIM
)
617 elapsed
= GetTickCount() - start
;
618 timeout
= elapsed
>= orig_timeout
? 0 : orig_timeout
- elapsed
;