1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2019 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 /* 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 /* Avoid warnings from gcc -Wcast-function-type. */
88 # define GetProcAddress \
89 (void *) GetProcAddress
91 static BOOL
IsConsoleHandle (HANDLE h
)
94 return GetConsoleMode (h
, &mode
) != 0;
98 IsSocketHandle (HANDLE h
)
102 if (IsConsoleHandle (h
))
105 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
106 WSAEnumNetworkEvents instead distinguishes the two correctly. */
107 ev
.lNetworkEvents
= 0xDEADBEEF;
108 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
109 return ev
.lNetworkEvents
!= 0xDEADBEEF;
112 /* Declare data structures for ntdll functions. */
113 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
115 ULONG NamedPipeConfiguration
;
116 ULONG MaximumInstances
;
117 ULONG CurrentInstances
;
119 ULONG ReadDataAvailable
;
121 ULONG WriteQuotaAvailable
;
122 ULONG NamedPipeState
;
124 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
126 typedef struct _IO_STATUS_BLOCK
132 ULONG_PTR Information
;
133 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
135 typedef enum _FILE_INFORMATION_CLASS
{
136 FilePipeLocalInformation
= 24
137 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
139 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
140 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
143 # define PIPE_BUF 512
146 /* Compute revents values for file handle H. If some events cannot happen
147 for the handle, eliminate them from *P_SOUGHT. */
150 windows_compute_revents (HANDLE h
, int *p_sought
)
152 int i
, ret
, happened
;
153 INPUT_RECORD
*irbuffer
;
154 DWORD avail
, nbuffer
;
156 IO_STATUS_BLOCK iosb
;
157 FILE_PIPE_LOCAL_INFORMATION fpli
;
158 static PNtQueryInformationFile NtQueryInformationFile
;
159 static BOOL once_only
;
161 switch (GetFileType (h
))
166 NtQueryInformationFile
= (PNtQueryInformationFile
)
167 GetProcAddress (GetModuleHandle ("ntdll.dll"),
168 "NtQueryInformationFile");
173 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
176 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
178 else if (GetLastError () == ERROR_BROKEN_PIPE
)
183 /* It was the write-end of the pipe. Check if it is writable.
184 If NtQueryInformationFile fails, optimistically assume the pipe is
185 writable. This could happen on Windows 9x, where
186 NtQueryInformationFile is not available, or if we inherit a pipe
187 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
188 (I think this should not happen since Windows XP SP2; WINE seems
189 fine too). Otherwise, ensure that enough space is available for
191 memset (&iosb
, 0, sizeof (iosb
));
192 memset (&fpli
, 0, sizeof (fpli
));
194 if (!NtQueryInformationFile
195 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
196 FilePipeLocalInformation
)
197 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
198 || (fpli
.OutboundQuota
< PIPE_BUF
&&
199 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
200 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
205 ret
= WaitForSingleObject (h
, 0);
206 if (!IsConsoleHandle (h
))
207 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
210 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
214 *p_sought
&= POLLIN
| POLLRDNORM
;
220 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
221 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
222 if (!bRet
|| avail
== 0)
225 for (i
= 0; i
< avail
; i
++)
226 if (irbuffer
[i
].EventType
== KEY_EVENT
)
233 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
238 ret
= WaitForSingleObject (h
, 0);
239 if (ret
== WAIT_OBJECT_0
)
240 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
242 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
246 /* Convert fd_sets returned by select into revents values. */
249 windows_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
253 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
254 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
256 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
262 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
263 error
= WSAGetLastError ();
266 if (r
> 0 || error
== WSAENOTCONN
)
267 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
269 /* Distinguish hung-up sockets from other errors. */
270 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
271 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
278 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
279 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
281 if (lNetworkEvents
& FD_OOB
)
282 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
289 /* Convert select(2) returned fd_sets into poll(2) revents values. */
291 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
294 if (FD_ISSET (fd
, rfds
))
299 # if defined __MACH__ && defined __APPLE__
300 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
301 for some kinds of descriptors. Detect if this descriptor is a
302 connected socket, a server socket, or something else using a
303 0-byte recv, and use ioctl(2) to detect POLLHUP. */
304 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
305 socket_errno
= (r
< 0) ? errno
: 0;
306 if (r
== 0 || socket_errno
== ENOTSOCK
)
307 ioctl (fd
, FIONREAD
, &r
);
310 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
311 socket_errno
= (r
< 0) ? errno
: 0;
316 /* If the event happened on an unconnected server socket,
318 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
319 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
321 /* Distinguish hung-up sockets from other errors. */
322 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
323 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
326 /* some systems can't use recv() on non-socket, including HP NonStop */
327 else if (socket_errno
== ENOTSOCK
)
328 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
334 if (FD_ISSET (fd
, wfds
))
335 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
337 if (FD_ISSET (fd
, efds
))
338 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
345 poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
347 #ifndef WINDOWS_NATIVE
348 fd_set rfds
, wfds
, efds
;
359 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
360 of a too-large NFD is caught by one of the other checks below, and
361 checking directly for getdtablesize is too much of a portability
362 and/or performance and/or correctness hassle. */
364 /* EFAULT is not necessary to implement, but let's do it in the
372 /* convert timeout number into a timeval structure */
379 else if (timeout
> 0)
382 ptv
->tv_sec
= timeout
/ 1000;
383 ptv
->tv_usec
= (timeout
% 1000) * 1000;
385 else if (timeout
== INFTIM
)
394 /* create fd sets and determine max fd */
399 for (i
= 0; i
< nfd
; i
++)
403 if (maxfd
< pfd
[i
].fd
)
406 if (FD_SETSIZE
<= maxfd
)
412 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
413 FD_SET (pfd
[i
].fd
, &rfds
);
414 /* see select(2): "the only exceptional condition detectable
415 is out-of-band data received on a socket", hence we push
416 POLLWRBAND events onto wfds instead of efds. */
417 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
418 FD_SET (pfd
[i
].fd
, &wfds
);
419 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
420 FD_SET (pfd
[i
].fd
, &efds
);
423 /* examine fd sets */
424 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
428 /* establish results */
430 for (i
= 0; i
< nfd
; i
++)
432 pfd
[i
].revents
= (pfd
[i
].fd
< 0
434 : compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
435 &rfds
, &wfds
, &efds
));
436 rc
+= pfd
[i
].revents
!= 0;
441 static struct timeval tv0
;
442 static HANDLE hEvent
;
444 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
445 DWORD ret
, wait_timeout
, nhandles
;
446 fd_set rfds
, wfds
, xfds
;
452 if (nfd
> INT_MAX
|| timeout
< -1)
459 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
462 handle_array
[0] = hEvent
;
468 /* Classify socket handles and create fd sets. */
469 for (i
= 0; i
< nfd
; i
++)
471 int sought
= pfd
[i
].events
;
475 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
476 | POLLPRI
| POLLRDBAND
)))
479 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
481 if (IsSocketHandle (h
))
483 int requested
= FD_CLOSE
;
485 /* see above; socket handles are mapped onto select. */
486 if (sought
& (POLLIN
| POLLRDNORM
))
488 requested
|= FD_READ
| FD_ACCEPT
;
489 FD_SET ((SOCKET
) h
, &rfds
);
491 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
493 requested
|= FD_WRITE
| FD_CONNECT
;
494 FD_SET ((SOCKET
) h
, &wfds
);
496 if (sought
& (POLLPRI
| POLLRDBAND
))
499 FD_SET ((SOCKET
) h
, &xfds
);
503 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
507 /* Poll now. If we get an event, do not poll again. Also,
508 screen buffer handles are waitable, and they'll block until
509 a character is available. windows_compute_revents eliminates
510 bits for the "wrong" direction. */
511 pfd
[i
].revents
= windows_compute_revents (h
, &sought
);
513 handle_array
[nhandles
++] = h
;
519 if (select (0, &rfds
, &wfds
, &xfds
, &tv0
) > 0)
521 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
522 no need to call select again. */
529 if (timeout
== INFTIM
)
530 wait_timeout
= INFINITE
;
532 wait_timeout
= timeout
;
537 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
538 wait_timeout
, QS_ALLINPUT
);
540 if (ret
== WAIT_OBJECT_0
+ nhandles
)
542 /* new input of some other kind */
544 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
546 TranslateMessage (&msg
);
547 DispatchMessage (&msg
);
555 select (0, &rfds
, &wfds
, &xfds
, &tv0
);
557 /* Place a sentinel at the end of the array. */
558 handle_array
[nhandles
] = NULL
;
560 for (i
= 0; i
< nfd
; i
++)
566 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
567 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
570 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
571 if (h
!= handle_array
[nhandles
])
574 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
575 WSAEventSelect ((SOCKET
) h
, 0, 0);
577 /* If we're lucky, WSAEnumNetworkEvents already provided a way
578 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
579 if (FD_ISSET ((SOCKET
) h
, &rfds
)
580 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
581 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
582 if (FD_ISSET ((SOCKET
) h
, &wfds
))
583 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
584 if (FD_ISSET ((SOCKET
) h
, &xfds
))
585 ev
.lNetworkEvents
|= FD_OOB
;
587 happened
= windows_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
593 int sought
= pfd
[i
].events
;
594 happened
= windows_compute_revents (h
, &sought
);
598 if ((pfd
[i
].revents
|= happened
) != 0)
602 if (!rc
&& timeout
== INFTIM
)