1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2018 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 <https://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"
29 #include <sys/types.h>
37 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
38 # define WINDOWS_NATIVE
39 # include <winsock2.h>
44 # if GNULIB_MSVC_NOTHROW
45 # include "msvc-nothrow.h"
50 # include <sys/time.h>
54 #include <sys/select.h>
55 #include <sys/socket.h>
57 #ifdef HAVE_SYS_IOCTL_H
58 # include <sys/ioctl.h>
60 #ifdef HAVE_SYS_FILIO_H
61 # include <sys/filio.h>
72 /* BeOS does not have MSG_PEEK. */
79 /* Here we need the recv() function from Windows, that takes a SOCKET as
80 first argument, not any possible gnulib override. */
83 /* Here we need the select() function from Windows, because we pass bit masks
84 of SOCKETs, not bit masks of FDs. */
87 static BOOL
IsConsoleHandle (HANDLE h
)
90 return GetConsoleMode (h
, &mode
) != 0;
94 IsSocketHandle (HANDLE h
)
98 if (IsConsoleHandle (h
))
101 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
102 WSAEnumNetworkEvents instead distinguishes the two correctly. */
103 ev
.lNetworkEvents
= 0xDEADBEEF;
104 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
105 return ev
.lNetworkEvents
!= 0xDEADBEEF;
108 /* Declare data structures for ntdll functions. */
109 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
111 ULONG NamedPipeConfiguration
;
112 ULONG MaximumInstances
;
113 ULONG CurrentInstances
;
115 ULONG ReadDataAvailable
;
117 ULONG WriteQuotaAvailable
;
118 ULONG NamedPipeState
;
120 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
122 typedef struct _IO_STATUS_BLOCK
128 ULONG_PTR Information
;
129 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
131 typedef enum _FILE_INFORMATION_CLASS
{
132 FilePipeLocalInformation
= 24
133 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
135 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
136 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
139 # define PIPE_BUF 512
142 /* Compute revents values for file handle H. If some events cannot happen
143 for the handle, eliminate them from *P_SOUGHT. */
146 windows_compute_revents (HANDLE h
, int *p_sought
)
148 int i
, ret
, happened
;
149 INPUT_RECORD
*irbuffer
;
150 DWORD avail
, nbuffer
;
152 IO_STATUS_BLOCK iosb
;
153 FILE_PIPE_LOCAL_INFORMATION fpli
;
154 static PNtQueryInformationFile NtQueryInformationFile
;
155 static BOOL once_only
;
157 switch (GetFileType (h
))
162 NtQueryInformationFile
= (PNtQueryInformationFile
)
163 GetProcAddress (GetModuleHandle ("ntdll.dll"),
164 "NtQueryInformationFile");
169 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
172 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
174 else if (GetLastError () == ERROR_BROKEN_PIPE
)
179 /* It was the write-end of the pipe. Check if it is writable.
180 If NtQueryInformationFile fails, optimistically assume the pipe is
181 writable. This could happen on Windows 9x, where
182 NtQueryInformationFile is not available, or if we inherit a pipe
183 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
184 (I think this should not happen since Windows XP SP2; WINE seems
185 fine too). Otherwise, ensure that enough space is available for
187 memset (&iosb
, 0, sizeof (iosb
));
188 memset (&fpli
, 0, sizeof (fpli
));
190 if (!NtQueryInformationFile
191 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
192 FilePipeLocalInformation
)
193 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
194 || (fpli
.OutboundQuota
< PIPE_BUF
&&
195 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
196 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
201 ret
= WaitForSingleObject (h
, 0);
202 if (!IsConsoleHandle (h
))
203 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
206 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
210 *p_sought
&= POLLIN
| POLLRDNORM
;
216 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
217 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
218 if (!bRet
|| avail
== 0)
221 for (i
= 0; i
< avail
; i
++)
222 if (irbuffer
[i
].EventType
== KEY_EVENT
)
229 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
234 ret
= WaitForSingleObject (h
, 0);
235 if (ret
== WAIT_OBJECT_0
)
236 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
238 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
242 /* Convert fd_sets returned by select into revents values. */
245 windows_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
249 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
250 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
252 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
258 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
259 error
= WSAGetLastError ();
262 if (r
> 0 || error
== WSAENOTCONN
)
263 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
265 /* Distinguish hung-up sockets from other errors. */
266 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
267 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
274 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
275 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
277 if (lNetworkEvents
& FD_OOB
)
278 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
285 /* Convert select(2) returned fd_sets into poll(2) revents values. */
287 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
290 if (FD_ISSET (fd
, rfds
))
295 # if defined __MACH__ && defined __APPLE__
296 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
297 for some kinds of descriptors. Detect if this descriptor is a
298 connected socket, a server socket, or something else using a
299 0-byte recv, and use ioctl(2) to detect POLLHUP. */
300 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
301 socket_errno
= (r
< 0) ? errno
: 0;
302 if (r
== 0 || socket_errno
== ENOTSOCK
)
303 ioctl (fd
, FIONREAD
, &r
);
306 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
307 socket_errno
= (r
< 0) ? errno
: 0;
312 /* If the event happened on an unconnected server socket,
314 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
315 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
317 /* Distinguish hung-up sockets from other errors. */
318 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
319 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
322 /* some systems can't use recv() on non-socket, including HP NonStop */
323 else if (socket_errno
== ENOTSOCK
)
324 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
330 if (FD_ISSET (fd
, wfds
))
331 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
333 if (FD_ISSET (fd
, efds
))
334 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
341 poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
343 #ifndef WINDOWS_NATIVE
344 fd_set rfds
, wfds
, efds
;
355 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
356 of a too-large NFD is caught by one of the other checks below, and
357 checking directly for getdtablesize is too much of a portability
358 and/or performance and/or correctness hassle. */
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
++)
399 if (maxfd
< pfd
[i
].fd
)
402 if (FD_SETSIZE
<= maxfd
)
408 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
409 FD_SET (pfd
[i
].fd
, &rfds
);
410 /* see select(2): "the only exceptional condition detectable
411 is out-of-band data received on a socket", hence we push
412 POLLWRBAND events onto wfds instead of efds. */
413 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
414 FD_SET (pfd
[i
].fd
, &wfds
);
415 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
416 FD_SET (pfd
[i
].fd
, &efds
);
419 /* examine fd sets */
420 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
424 /* establish results */
426 for (i
= 0; i
< nfd
; i
++)
428 pfd
[i
].revents
= (pfd
[i
].fd
< 0
430 : compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
431 &rfds
, &wfds
, &efds
));
432 rc
+= pfd
[i
].revents
!= 0;
437 static struct timeval tv0
;
438 static HANDLE hEvent
;
440 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
441 DWORD ret
, wait_timeout
, nhandles
;
442 fd_set rfds
, wfds
, xfds
;
448 if (nfd
> INT_MAX
|| timeout
< -1)
455 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
458 handle_array
[0] = hEvent
;
464 /* Classify socket handles and create fd sets. */
465 for (i
= 0; i
< nfd
; i
++)
467 int sought
= pfd
[i
].events
;
471 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
472 | POLLPRI
| POLLRDBAND
)))
475 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
477 if (IsSocketHandle (h
))
479 int requested
= FD_CLOSE
;
481 /* see above; socket handles are mapped onto select. */
482 if (sought
& (POLLIN
| POLLRDNORM
))
484 requested
|= FD_READ
| FD_ACCEPT
;
485 FD_SET ((SOCKET
) h
, &rfds
);
487 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
489 requested
|= FD_WRITE
| FD_CONNECT
;
490 FD_SET ((SOCKET
) h
, &wfds
);
492 if (sought
& (POLLPRI
| POLLRDBAND
))
495 FD_SET ((SOCKET
) h
, &xfds
);
499 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
503 /* Poll now. If we get an event, do not poll again. Also,
504 screen buffer handles are waitable, and they'll block until
505 a character is available. windows_compute_revents eliminates
506 bits for the "wrong" direction. */
507 pfd
[i
].revents
= windows_compute_revents (h
, &sought
);
509 handle_array
[nhandles
++] = h
;
515 if (select (0, &rfds
, &wfds
, &xfds
, &tv0
) > 0)
517 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
518 no need to call select again. */
525 if (timeout
== INFTIM
)
526 wait_timeout
= INFINITE
;
528 wait_timeout
= timeout
;
533 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
534 wait_timeout
, QS_ALLINPUT
);
536 if (ret
== WAIT_OBJECT_0
+ nhandles
)
538 /* new input of some other kind */
540 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
542 TranslateMessage (&msg
);
543 DispatchMessage (&msg
);
551 select (0, &rfds
, &wfds
, &xfds
, &tv0
);
553 /* Place a sentinel at the end of the array. */
554 handle_array
[nhandles
] = NULL
;
556 for (i
= 0; i
< nfd
; i
++)
562 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
563 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
566 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
567 if (h
!= handle_array
[nhandles
])
570 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
571 WSAEventSelect ((SOCKET
) h
, 0, 0);
573 /* If we're lucky, WSAEnumNetworkEvents already provided a way
574 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
575 if (FD_ISSET ((SOCKET
) h
, &rfds
)
576 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
577 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
578 if (FD_ISSET ((SOCKET
) h
, &wfds
))
579 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
580 if (FD_ISSET ((SOCKET
) h
, &xfds
))
581 ev
.lNetworkEvents
|= FD_OOB
;
583 happened
= windows_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
589 int sought
= pfd
[i
].events
;
590 happened
= windows_compute_revents (h
, &sought
);
594 if ((pfd
[i
].revents
|= happened
) != 0)
598 if (!rc
&& timeout
== INFTIM
)