1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2020 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 __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 /* Don't assume that UNICODE is not defined. */
80 # undef GetModuleHandle
81 # define GetModuleHandle GetModuleHandleA
82 # undef PeekConsoleInput
83 # define PeekConsoleInput PeekConsoleInputA
85 # define CreateEvent CreateEventA
87 # define PeekMessage PeekMessageA
88 # undef DispatchMessage
89 # define DispatchMessage DispatchMessageA
91 /* Do *not* use the function WSAPoll
92 <https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsapoll>
93 because there is a bug named “Windows 8 Bugs 309411 - WSAPoll does not
94 report failed connections” that Microsoft won't fix.
95 See Daniel Stenberg: "WASPoll is broken"
96 <https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/>. */
98 /* Here we need the recv() function from Windows, that takes a SOCKET as
99 first argument, not any possible gnulib override. */
102 /* Here we need the select() function from Windows, because we pass bit masks
103 of SOCKETs, not bit masks of FDs. */
106 /* Here we need timeval from Windows since this is what the select() function
107 from Windows requires. */
110 /* Avoid warnings from gcc -Wcast-function-type. */
111 # define GetProcAddress \
112 (void *) GetProcAddress
114 static BOOL
IsConsoleHandle (HANDLE h
)
117 return GetConsoleMode (h
, &mode
) != 0;
121 IsSocketHandle (HANDLE h
)
125 if (IsConsoleHandle (h
))
128 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
129 WSAEnumNetworkEvents instead distinguishes the two correctly. */
130 ev
.lNetworkEvents
= 0xDEADBEEF;
131 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
132 return ev
.lNetworkEvents
!= 0xDEADBEEF;
135 /* Declare data structures for ntdll functions. */
136 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
138 ULONG NamedPipeConfiguration
;
139 ULONG MaximumInstances
;
140 ULONG CurrentInstances
;
142 ULONG ReadDataAvailable
;
144 ULONG WriteQuotaAvailable
;
145 ULONG NamedPipeState
;
147 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
149 typedef struct _IO_STATUS_BLOCK
155 ULONG_PTR Information
;
156 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
158 typedef enum _FILE_INFORMATION_CLASS
{
159 FilePipeLocalInformation
= 24
160 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
162 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
163 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
166 # define PIPE_BUF 512
169 /* Compute revents values for file handle H. If some events cannot happen
170 for the handle, eliminate them from *P_SOUGHT. */
173 windows_compute_revents (HANDLE h
, int *p_sought
)
175 int i
, ret
, happened
;
176 INPUT_RECORD
*irbuffer
;
177 DWORD avail
, nbuffer
;
179 IO_STATUS_BLOCK iosb
;
180 FILE_PIPE_LOCAL_INFORMATION fpli
;
181 static PNtQueryInformationFile NtQueryInformationFile
;
182 static BOOL once_only
;
184 switch (GetFileType (h
))
189 NtQueryInformationFile
= (PNtQueryInformationFile
)
190 GetProcAddress (GetModuleHandle ("ntdll.dll"),
191 "NtQueryInformationFile");
196 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
199 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
201 else if (GetLastError () == ERROR_BROKEN_PIPE
)
206 /* It was the write-end of the pipe. Check if it is writable.
207 If NtQueryInformationFile fails, optimistically assume the pipe is
208 writable. This could happen on Windows 9x, where
209 NtQueryInformationFile is not available, or if we inherit a pipe
210 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
211 (I think this should not happen since Windows XP SP2; WINE seems
212 fine too). Otherwise, ensure that enough space is available for
214 memset (&iosb
, 0, sizeof (iosb
));
215 memset (&fpli
, 0, sizeof (fpli
));
217 if (!NtQueryInformationFile
218 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
219 FilePipeLocalInformation
)
220 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
221 || (fpli
.OutboundQuota
< PIPE_BUF
&&
222 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
223 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
228 ret
= WaitForSingleObject (h
, 0);
229 if (!IsConsoleHandle (h
))
230 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
233 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
237 *p_sought
&= POLLIN
| POLLRDNORM
;
243 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
244 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
245 if (!bRet
|| avail
== 0)
248 for (i
= 0; i
< avail
; i
++)
249 if (irbuffer
[i
].EventType
== KEY_EVENT
)
256 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
261 ret
= WaitForSingleObject (h
, 0);
262 if (ret
== WAIT_OBJECT_0
)
263 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
265 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
269 /* Convert fd_sets returned by select into revents values. */
272 windows_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
276 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
277 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
279 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
285 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
286 error
= WSAGetLastError ();
289 if (r
> 0 || error
== WSAENOTCONN
)
290 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
292 /* Distinguish hung-up sockets from other errors. */
293 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
294 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
301 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
302 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
304 if (lNetworkEvents
& FD_OOB
)
305 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
312 /* Convert select(2) returned fd_sets into poll(2) revents values. */
314 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
317 if (FD_ISSET (fd
, rfds
))
322 # if defined __MACH__ && defined __APPLE__
323 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
324 for some kinds of descriptors. Detect if this descriptor is a
325 connected socket, a server socket, or something else using a
326 0-byte recv, and use ioctl(2) to detect POLLHUP. */
327 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
328 socket_errno
= (r
< 0) ? errno
: 0;
329 if (r
== 0 || socket_errno
== ENOTSOCK
)
330 ioctl (fd
, FIONREAD
, &r
);
333 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
334 socket_errno
= (r
< 0) ? errno
: 0;
339 /* If the event happened on an unconnected server socket,
341 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
342 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
344 /* Distinguish hung-up sockets from other errors. */
345 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
346 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
349 /* some systems can't use recv() on non-socket, including HP NonStop */
350 else if (socket_errno
== ENOTSOCK
)
351 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
357 if (FD_ISSET (fd
, wfds
))
358 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
360 if (FD_ISSET (fd
, efds
))
361 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
368 poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
370 #ifndef WINDOWS_NATIVE
371 fd_set rfds
, wfds
, efds
;
382 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
383 of a too-large NFD is caught by one of the other checks below, and
384 checking directly for getdtablesize is too much of a portability
385 and/or performance and/or correctness hassle. */
387 /* EFAULT is not necessary to implement, but let's do it in the
395 /* convert timeout number into a timeval structure */
402 else if (timeout
> 0)
405 ptv
->tv_sec
= timeout
/ 1000;
406 ptv
->tv_usec
= (timeout
% 1000) * 1000;
408 else if (timeout
== INFTIM
)
417 /* create fd sets and determine max fd */
422 for (i
= 0; i
< nfd
; i
++)
426 if (maxfd
< pfd
[i
].fd
)
429 if (FD_SETSIZE
<= maxfd
)
435 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
436 FD_SET (pfd
[i
].fd
, &rfds
);
437 /* see select(2): "the only exceptional condition detectable
438 is out-of-band data received on a socket", hence we push
439 POLLWRBAND events onto wfds instead of efds. */
440 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
441 FD_SET (pfd
[i
].fd
, &wfds
);
442 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
443 FD_SET (pfd
[i
].fd
, &efds
);
446 /* examine fd sets */
447 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
451 /* establish results */
453 for (i
= 0; i
< nfd
; i
++)
455 pfd
[i
].revents
= (pfd
[i
].fd
< 0
457 : compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
458 &rfds
, &wfds
, &efds
));
459 rc
+= pfd
[i
].revents
!= 0;
464 static struct timeval tv0
;
465 static HANDLE hEvent
;
467 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
468 DWORD ret
, wait_timeout
, nhandles
;
469 fd_set rfds
, wfds
, xfds
;
475 if (nfd
> INT_MAX
|| timeout
< -1)
482 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
485 handle_array
[0] = hEvent
;
491 /* Classify socket handles and create fd sets. */
492 for (i
= 0; i
< nfd
; i
++)
494 int sought
= pfd
[i
].events
;
498 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
499 | POLLPRI
| POLLRDBAND
)))
502 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
504 if (IsSocketHandle (h
))
506 int requested
= FD_CLOSE
;
508 /* see above; socket handles are mapped onto select. */
509 if (sought
& (POLLIN
| POLLRDNORM
))
511 requested
|= FD_READ
| FD_ACCEPT
;
512 FD_SET ((SOCKET
) h
, &rfds
);
514 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
516 requested
|= FD_WRITE
| FD_CONNECT
;
517 FD_SET ((SOCKET
) h
, &wfds
);
519 if (sought
& (POLLPRI
| POLLRDBAND
))
522 FD_SET ((SOCKET
) h
, &xfds
);
526 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
530 /* Poll now. If we get an event, do not poll again. Also,
531 screen buffer handles are waitable, and they'll block until
532 a character is available. windows_compute_revents eliminates
533 bits for the "wrong" direction. */
534 pfd
[i
].revents
= windows_compute_revents (h
, &sought
);
536 handle_array
[nhandles
++] = h
;
542 if (select (0, &rfds
, &wfds
, &xfds
, &tv0
) > 0)
544 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
545 no need to call select again. */
552 if (timeout
== INFTIM
)
553 wait_timeout
= INFINITE
;
555 wait_timeout
= timeout
;
560 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
561 wait_timeout
, QS_ALLINPUT
);
563 if (ret
== WAIT_OBJECT_0
+ nhandles
)
565 /* new input of some other kind */
567 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
569 TranslateMessage (&msg
);
570 DispatchMessage (&msg
);
578 select (0, &rfds
, &wfds
, &xfds
, &tv0
);
580 /* Place a sentinel at the end of the array. */
581 handle_array
[nhandles
] = NULL
;
583 for (i
= 0; i
< nfd
; i
++)
589 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
590 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
593 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
594 if (h
!= handle_array
[nhandles
])
597 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
598 WSAEventSelect ((SOCKET
) h
, 0, 0);
600 /* If we're lucky, WSAEnumNetworkEvents already provided a way
601 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
602 if (FD_ISSET ((SOCKET
) h
, &rfds
)
603 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
604 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
605 if (FD_ISSET ((SOCKET
) h
, &wfds
))
606 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
607 if (FD_ISSET ((SOCKET
) h
, &xfds
))
608 ev
.lNetworkEvents
|= FD_OOB
;
610 happened
= windows_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
616 int sought
= pfd
[i
].events
;
617 happened
= windows_compute_revents (h
, &sought
);
621 if ((pfd
[i
].revents
|= happened
) != 0)
625 if (!rc
&& timeout
== INFTIM
)