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 /* To bump the minimum Windows version to Windows Vista */
22 #include "git-compat-util.h"
24 /* Tell gcc not to warn about the (nfd < 0) tests, below. */
25 #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
26 # pragma GCC diagnostic ignored "-Wtype-limits"
33 #include <sys/types.h>
39 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
41 # if defined (_MSC_VER) && !defined(_WIN32_WINNT)
42 # define _WIN32_WINNT 0x0502
44 # include <winsock2.h>
50 # include <sys/time.h>
51 # include <sys/socket.h>
52 # ifndef NO_SYS_SELECT_H
53 # include <sys/select.h>
61 #ifdef HAVE_SYS_IOCTL_H
62 # include <sys/ioctl.h>
64 #ifdef HAVE_SYS_FILIO_H
65 # include <sys/filio.h>
74 /* BeOS does not have MSG_PEEK. */
81 #define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
84 IsSocketHandle (HANDLE h
)
88 if (IsConsoleHandle (h
))
91 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
92 WSAEnumNetworkEvents instead distinguishes the two correctly. */
93 ev
.lNetworkEvents
= 0xDEADBEEF;
94 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
95 return ev
.lNetworkEvents
!= 0xDEADBEEF;
98 /* Declare data structures for ntdll functions. */
99 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
101 ULONG NamedPipeConfiguration
;
102 ULONG MaximumInstances
;
103 ULONG CurrentInstances
;
105 ULONG ReadDataAvailable
;
107 ULONG WriteQuotaAvailable
;
108 ULONG NamedPipeState
;
110 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
112 typedef struct _IO_STATUS_BLOCK
118 ULONG_PTR Information
;
119 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
121 typedef enum _FILE_INFORMATION_CLASS
{
122 FilePipeLocalInformation
= 24
123 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
125 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
126 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
129 # define PIPE_BUF 512
132 /* Compute revents values for file handle H. If some events cannot happen
133 for the handle, eliminate them from *P_SOUGHT. */
136 win32_compute_revents (HANDLE h
, int *p_sought
)
138 int i
, ret
, happened
;
139 INPUT_RECORD
*irbuffer
;
140 DWORD avail
, nbuffer
;
142 IO_STATUS_BLOCK iosb
;
143 FILE_PIPE_LOCAL_INFORMATION fpli
;
144 static PNtQueryInformationFile NtQueryInformationFile
;
145 static BOOL once_only
;
147 switch (GetFileType (h
))
152 NtQueryInformationFile
= (PNtQueryInformationFile
)
153 GetProcAddress (GetModuleHandle ("ntdll.dll"),
154 "NtQueryInformationFile");
159 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
162 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
164 else if (GetLastError () == ERROR_BROKEN_PIPE
)
169 /* It was the write-end of the pipe. Check if it is writable.
170 If NtQueryInformationFile fails, optimistically assume the pipe is
171 writable. This could happen on Win9x, where NtQueryInformationFile
172 is not available, or if we inherit a pipe that doesn't permit
173 FILE_READ_ATTRIBUTES access on the write end (I think this should
174 not happen since WinXP SP2; WINE seems fine too). Otherwise,
175 ensure that enough space is available for atomic writes. */
176 memset (&iosb
, 0, sizeof (iosb
));
177 memset (&fpli
, 0, sizeof (fpli
));
179 if (!NtQueryInformationFile
180 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
181 FilePipeLocalInformation
)
182 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
183 || (fpli
.OutboundQuota
< PIPE_BUF
&&
184 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
185 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
190 ret
= WaitForSingleObject (h
, 0);
191 if (!IsConsoleHandle (h
))
192 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
195 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
199 *p_sought
&= POLLIN
| POLLRDNORM
;
205 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
206 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
207 if (!bRet
|| avail
== 0)
210 for (i
= 0; i
< avail
; i
++)
211 if (irbuffer
[i
].EventType
== KEY_EVENT
)
218 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
223 ret
= WaitForSingleObject (h
, 0);
224 if (ret
== WAIT_OBJECT_0
)
225 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
227 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
231 /* Convert fd_sets returned by select into revents values. */
234 win32_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
238 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
239 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
241 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
247 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
248 error
= WSAGetLastError ();
251 if (r
> 0 || error
== WSAENOTCONN
)
252 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
254 /* Distinguish hung-up sockets from other errors. */
255 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
256 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
263 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
264 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
266 if (lNetworkEvents
& FD_OOB
)
267 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
274 /* Convert select(2) returned fd_sets into poll(2) revents values. */
276 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
279 if (FD_ISSET (fd
, rfds
))
284 # if defined __MACH__ && defined __APPLE__
285 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
286 for some kinds of descriptors. Detect if this descriptor is a
287 connected socket, a server socket, or something else using a
288 0-byte recv, and use ioctl(2) to detect POLLHUP. */
289 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
290 socket_errno
= (r
< 0) ? errno
: 0;
291 if (r
== 0 || socket_errno
== ENOTSOCK
)
292 ioctl (fd
, FIONREAD
, &r
);
295 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
296 socket_errno
= (r
< 0) ? errno
: 0;
301 /* If the event happened on an unconnected server socket,
303 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
304 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
306 /* Distinguish hung-up sockets from other errors. */
307 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
308 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
311 /* some systems can't use recv() on non-socket, including HP NonStop */
312 else if (/* (r == -1) && */ socket_errno
== ENOTSOCK
)
313 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
319 if (FD_ISSET (fd
, wfds
))
320 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
322 if (FD_ISSET (fd
, efds
))
323 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
330 poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
333 fd_set rfds
, wfds
, efds
;
340 static int sc_open_max
= -1;
343 || (nfd
> sc_open_max
344 && (sc_open_max
!= -1
345 || nfd
> (sc_open_max
= sysconf (_SC_OPEN_MAX
)))))
350 # else /* !_SC_OPEN_MAX */
352 if (nfd
< 0 || nfd
> OPEN_MAX
)
357 # endif /* OPEN_MAX -- else, no check is needed */
358 # endif /* !_SC_OPEN_MAX */
360 /* EFAULT is not necessary to implement, but let's do it in the
368 /* convert timeout number into a timeval structure */
375 else if (timeout
> 0)
378 ptv
->tv_sec
= timeout
/ 1000;
379 ptv
->tv_usec
= (timeout
% 1000) * 1000;
381 else if (timeout
== INFTIM
)
390 /* create fd sets and determine max fd */
395 for (i
= 0; i
< nfd
; i
++)
400 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
401 FD_SET (pfd
[i
].fd
, &rfds
);
403 /* see select(2): "the only exceptional condition detectable
404 is out-of-band data received on a socket", hence we push
405 POLLWRBAND events onto wfds instead of efds. */
406 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
407 FD_SET (pfd
[i
].fd
, &wfds
);
408 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
409 FD_SET (pfd
[i
].fd
, &efds
);
410 if (pfd
[i
].fd
>= maxfd
411 && (pfd
[i
].events
& (POLLIN
| POLLOUT
| POLLPRI
412 | POLLRDNORM
| POLLRDBAND
413 | POLLWRNORM
| POLLWRBAND
)))
416 if (maxfd
> FD_SETSIZE
)
424 /* examine fd sets */
425 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
429 /* establish results */
431 for (i
= 0; i
< nfd
; i
++)
436 int happened
= compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
437 &rfds
, &wfds
, &efds
);
440 pfd
[i
].revents
= happened
;
451 static struct timeval tv0
;
452 static HANDLE hEvent
;
454 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
455 DWORD ret
, wait_timeout
, nhandles
, orig_timeout
= 0;
457 fd_set rfds
, wfds
, xfds
;
463 if (nfd
< 0 || timeout
< -1)
469 if (timeout
!= INFTIM
)
471 orig_timeout
= timeout
;
472 start
= GetTickCount64();
476 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
479 handle_array
[0] = hEvent
;
485 /* Classify socket handles and create fd sets. */
486 for (i
= 0; i
< nfd
; i
++)
488 int sought
= pfd
[i
].events
;
492 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
493 | POLLPRI
| POLLRDBAND
)))
496 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
498 if (IsSocketHandle (h
))
500 int requested
= FD_CLOSE
;
502 /* see above; socket handles are mapped onto select. */
503 if (sought
& (POLLIN
| POLLRDNORM
))
505 requested
|= FD_READ
| FD_ACCEPT
;
506 FD_SET ((SOCKET
) h
, &rfds
);
508 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
510 requested
|= FD_WRITE
| FD_CONNECT
;
511 FD_SET ((SOCKET
) h
, &wfds
);
513 if (sought
& (POLLPRI
| POLLRDBAND
))
516 FD_SET ((SOCKET
) h
, &xfds
);
520 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
524 /* Poll now. If we get an event, do not poll again. Also,
525 screen buffer handles are waitable, and they'll block until
526 a character is available. win32_compute_revents eliminates
527 bits for the "wrong" direction. */
528 pfd
[i
].revents
= win32_compute_revents (h
, &sought
);
530 handle_array
[nhandles
++] = h
;
536 if (select (0, &rfds
, &wfds
, &xfds
, &tv0
) > 0)
538 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
539 no need to call select again. */
546 if (timeout
== INFTIM
)
547 wait_timeout
= INFINITE
;
549 wait_timeout
= timeout
;
554 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
555 wait_timeout
, QS_ALLINPUT
);
557 if (ret
== WAIT_OBJECT_0
+ nhandles
)
559 /* new input of some other kind */
561 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
563 TranslateMessage (&msg
);
564 DispatchMessage (&msg
);
572 select (0, &rfds
, &wfds
, &xfds
, &tv0
);
574 /* Place a sentinel at the end of the array. */
575 handle_array
[nhandles
] = NULL
;
577 for (i
= 0; i
< nfd
; i
++)
583 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
584 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
587 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
588 if (h
!= handle_array
[nhandles
])
591 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
592 WSAEventSelect ((SOCKET
) h
, NULL
, 0);
594 /* If we're lucky, WSAEnumNetworkEvents already provided a way
595 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
596 if (FD_ISSET ((SOCKET
) h
, &rfds
)
597 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
598 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
599 if (FD_ISSET ((SOCKET
) h
, &wfds
))
600 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
601 if (FD_ISSET ((SOCKET
) h
, &xfds
))
602 ev
.lNetworkEvents
|= FD_OOB
;
604 happened
= win32_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
610 int sought
= pfd
[i
].events
;
611 happened
= win32_compute_revents (h
, &sought
);
615 if ((pfd
[i
].revents
|= happened
) != 0)
619 if (!rc
&& orig_timeout
&& timeout
!= INFTIM
)
621 ULONGLONG elapsed
= GetTickCount64() - start
;
622 timeout
= elapsed
>= orig_timeout
? 0 : (int)(orig_timeout
- elapsed
);