1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2024 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This file is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 This file 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 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>. */
24 #include <sys/types.h>
32 #if defined _WIN32 && ! defined __CYGWIN__
33 # define WINDOWS_NATIVE
34 # include <winsock2.h>
39 # if GNULIB_MSVC_NOTHROW
40 # include "msvc-nothrow.h"
45 # include <sys/time.h>
49 #include <sys/select.h>
50 #include <sys/socket.h>
52 #ifdef HAVE_SYS_IOCTL_H
53 # include <sys/ioctl.h>
55 #ifdef HAVE_SYS_FILIO_H
56 # include <sys/filio.h>
67 /* BeOS does not have MSG_PEEK. */
74 /* Don't assume that UNICODE is not defined. */
75 # undef GetModuleHandle
76 # define GetModuleHandle GetModuleHandleA
77 # undef PeekConsoleInput
78 # define PeekConsoleInput PeekConsoleInputA
80 # define CreateEvent CreateEventA
82 # define PeekMessage PeekMessageA
83 # undef DispatchMessage
84 # define DispatchMessage DispatchMessageA
86 /* Do *not* use the function WSAPoll
87 <https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsapoll>
88 because there is a bug named “Windows 8 Bugs 309411 - WSAPoll does not
89 report failed connections” that Microsoft won't fix.
90 See Daniel Stenberg: "WASPoll is broken"
91 <https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/>. */
93 /* Here we need the recv() function from Windows, that takes a SOCKET as
94 first argument, not any possible gnulib override. */
97 /* Here we need the select() function from Windows, because we pass bit masks
98 of SOCKETs, not bit masks of FDs. */
101 /* Here we need timeval from Windows since this is what the select() function
102 from Windows requires. */
105 /* Avoid warnings from gcc -Wcast-function-type. */
106 # define GetProcAddress \
107 (void *) GetProcAddress
109 static BOOL
IsConsoleHandle (HANDLE h
)
112 return GetConsoleMode (h
, &mode
) != 0;
116 IsSocketHandle (HANDLE h
)
120 if (IsConsoleHandle (h
))
123 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
124 WSAEnumNetworkEvents instead distinguishes the two correctly. */
125 ev
.lNetworkEvents
= 0xDEADBEEF;
126 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
127 return ev
.lNetworkEvents
!= 0xDEADBEEF;
130 /* Declare data structures for ntdll functions. */
131 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
133 ULONG NamedPipeConfiguration
;
134 ULONG MaximumInstances
;
135 ULONG CurrentInstances
;
137 ULONG ReadDataAvailable
;
139 ULONG WriteQuotaAvailable
;
140 ULONG NamedPipeState
;
142 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
144 typedef struct _IO_STATUS_BLOCK
150 ULONG_PTR Information
;
151 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
153 typedef enum _FILE_INFORMATION_CLASS
{
154 FilePipeLocalInformation
= 24
155 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
157 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
158 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
161 # define PIPE_BUF 512
164 /* Compute revents values for file handle H. If some events cannot happen
165 for the handle, eliminate them from *P_SOUGHT. */
168 windows_compute_revents (HANDLE h
, int *p_sought
)
170 int i
, ret
, happened
;
171 INPUT_RECORD
*irbuffer
;
172 DWORD avail
, nbuffer
;
174 IO_STATUS_BLOCK iosb
;
175 FILE_PIPE_LOCAL_INFORMATION fpli
;
176 static PNtQueryInformationFile NtQueryInformationFile
;
177 static BOOL once_only
;
179 switch (GetFileType (h
))
184 NtQueryInformationFile
= (PNtQueryInformationFile
)
185 GetProcAddress (GetModuleHandle ("ntdll.dll"),
186 "NtQueryInformationFile");
191 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
194 happened
|= *p_sought
& (POLLIN
| POLLRDNORM
);
196 else if (GetLastError () == ERROR_BROKEN_PIPE
)
201 /* It was the write-end of the pipe. Check if it is writable.
202 If NtQueryInformationFile fails, optimistically assume the pipe is
203 writable. This could happen on Windows 9x, where
204 NtQueryInformationFile is not available, or if we inherit a pipe
205 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
206 (I think this should not happen since Windows XP SP2; WINE seems
207 fine too). Otherwise, ensure that enough space is available for
209 memset (&iosb
, 0, sizeof (iosb
));
210 memset (&fpli
, 0, sizeof (fpli
));
212 if (!NtQueryInformationFile
213 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
214 FilePipeLocalInformation
)
215 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
216 || (fpli
.OutboundQuota
< PIPE_BUF
&&
217 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
218 happened
|= *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
223 ret
= WaitForSingleObject (h
, 0);
224 if (!IsConsoleHandle (h
))
225 return ret
== WAIT_OBJECT_0
? *p_sought
& ~(POLLPRI
| POLLRDBAND
) : 0;
228 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
232 *p_sought
&= POLLIN
| POLLRDNORM
;
238 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
239 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
240 if (!bRet
|| avail
== 0)
243 for (i
= 0; i
< avail
; i
++)
244 if (irbuffer
[i
].EventType
== KEY_EVENT
)
251 *p_sought
&= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
256 ret
= WaitForSingleObject (h
, 0);
257 if (ret
== WAIT_OBJECT_0
)
258 return *p_sought
& ~(POLLPRI
| POLLRDBAND
);
260 return *p_sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
);
264 /* Convert fd_sets returned by select into revents values. */
267 windows_compute_revents_socket (SOCKET h
, int sought
, long lNetworkEvents
)
271 if ((lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
)) == FD_ACCEPT
)
272 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
274 else if (lNetworkEvents
& (FD_READ
| FD_ACCEPT
| FD_CLOSE
))
280 r
= recv (h
, data
, sizeof (data
), MSG_PEEK
);
281 error
= WSAGetLastError ();
284 if (r
> 0 || error
== WSAENOTCONN
)
285 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
287 /* Distinguish hung-up sockets from other errors. */
288 else if (r
== 0 || error
== WSAESHUTDOWN
|| error
== WSAECONNRESET
289 || error
== WSAECONNABORTED
|| error
== WSAENETRESET
)
296 if (lNetworkEvents
& (FD_WRITE
| FD_CONNECT
))
297 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
299 if (lNetworkEvents
& FD_OOB
)
300 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
307 /* Convert select(2) returned fd_sets into poll(2) revents values. */
309 compute_revents (int fd
, int sought
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
)
312 if (FD_ISSET (fd
, rfds
))
317 # if defined __MACH__ && defined __APPLE__
318 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
319 for some kinds of descriptors. Detect if this descriptor is a
320 connected socket, a server socket, or something else using a
321 0-byte recv, and use ioctl(2) to detect POLLHUP. */
322 r
= recv (fd
, NULL
, 0, MSG_PEEK
);
323 socket_errno
= (r
< 0) ? errno
: 0;
324 if (r
== 0 || socket_errno
== ENOTSOCK
)
325 ioctl (fd
, FIONREAD
, &r
);
328 r
= recv (fd
, data
, sizeof (data
), MSG_PEEK
);
329 socket_errno
= (r
< 0) ? errno
: 0;
334 /* If the event happened on an unconnected server socket,
336 else if (r
> 0 || ( /* (r == -1) && */ socket_errno
== ENOTCONN
))
337 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
339 /* Distinguish hung-up sockets from other errors. */
340 else if (socket_errno
== ESHUTDOWN
|| socket_errno
== ECONNRESET
341 || socket_errno
== ECONNABORTED
|| socket_errno
== ENETRESET
)
344 /* some systems can't use recv() on non-socket, including HP NonStop */
345 else if (socket_errno
== ENOTSOCK
)
346 happened
|= (POLLIN
| POLLRDNORM
) & sought
;
352 if (FD_ISSET (fd
, wfds
))
353 happened
|= (POLLOUT
| POLLWRNORM
| POLLWRBAND
) & sought
;
355 if (FD_ISSET (fd
, efds
))
356 happened
|= (POLLPRI
| POLLRDBAND
) & sought
;
363 poll (struct pollfd
*pfd
, nfds_t nfd
, int timeout
)
365 #ifndef WINDOWS_NATIVE
366 fd_set rfds
, wfds
, efds
;
377 /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
378 of a too-large NFD is caught by one of the other checks below, and
379 checking directly for getdtablesize is too much of a portability
380 and/or performance and/or correctness hassle. */
382 /* EFAULT is not necessary to implement, but let's do it in the
390 /* convert timeout number into a timeval structure */
394 tv
= (struct timeval
) {0};
396 else if (timeout
> 0)
399 tv
= (struct timeval
) {
400 .tv_sec
= timeout
/ 1000,
401 .tv_usec
= (timeout
% 1000) * 1000
404 else if (timeout
== INFTIM
)
413 /* create fd sets and determine max fd */
418 for (i
= 0; i
< nfd
; i
++)
422 if (maxfd
< pfd
[i
].fd
)
425 if (FD_SETSIZE
<= maxfd
)
431 if (pfd
[i
].events
& (POLLIN
| POLLRDNORM
))
432 FD_SET (pfd
[i
].fd
, &rfds
);
433 /* see select(2): "the only exceptional condition detectable
434 is out-of-band data received on a socket", hence we push
435 POLLWRBAND events onto wfds instead of efds. */
436 if (pfd
[i
].events
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
437 FD_SET (pfd
[i
].fd
, &wfds
);
438 if (pfd
[i
].events
& (POLLPRI
| POLLRDBAND
))
439 FD_SET (pfd
[i
].fd
, &efds
);
442 /* examine fd sets */
443 rc
= select (maxfd
+ 1, &rfds
, &wfds
, &efds
, ptv
);
447 /* establish results */
449 for (i
= 0; i
< nfd
; i
++)
451 pfd
[i
].revents
= (pfd
[i
].fd
< 0
453 : compute_revents (pfd
[i
].fd
, pfd
[i
].events
,
454 &rfds
, &wfds
, &efds
));
455 rc
+= pfd
[i
].revents
!= 0;
460 static struct timeval tv0
;
461 static HANDLE hEvent
;
463 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
464 DWORD ret
, wait_timeout
, nhandles
;
465 fd_set rfds
, wfds
, xfds
;
471 if (nfd
> INT_MAX
|| timeout
< -1)
478 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
481 handle_array
[0] = hEvent
;
487 /* Classify socket handles and create fd sets. */
488 for (i
= 0; i
< nfd
; i
++)
490 int sought
= pfd
[i
].events
;
494 if (!(sought
& (POLLIN
| POLLRDNORM
| POLLOUT
| POLLWRNORM
| POLLWRBAND
495 | POLLPRI
| POLLRDBAND
)))
498 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
500 if (IsSocketHandle (h
))
502 int requested
= FD_CLOSE
;
504 /* see above; socket handles are mapped onto select. */
505 if (sought
& (POLLIN
| POLLRDNORM
))
507 requested
|= FD_READ
| FD_ACCEPT
;
508 FD_SET ((SOCKET
) h
, &rfds
);
510 if (sought
& (POLLOUT
| POLLWRNORM
| POLLWRBAND
))
512 requested
|= FD_WRITE
| FD_CONNECT
;
513 FD_SET ((SOCKET
) h
, &wfds
);
515 if (sought
& (POLLPRI
| POLLRDBAND
))
518 FD_SET ((SOCKET
) h
, &xfds
);
522 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
526 /* Poll now. If we get an event, do not poll again. Also,
527 screen buffer handles are waitable, and they'll block until
528 a character is available. windows_compute_revents eliminates
529 bits for the "wrong" direction. */
530 pfd
[i
].revents
= windows_compute_revents (h
, &sought
);
532 handle_array
[nhandles
++] = h
;
538 if (select (0, &rfds
, &wfds
, &xfds
, &tv0
) > 0)
540 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
541 no need to call select again. */
548 if (timeout
== INFTIM
)
549 wait_timeout
= INFINITE
;
551 wait_timeout
= timeout
;
556 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
557 wait_timeout
, QS_ALLINPUT
);
559 if (ret
== WAIT_OBJECT_0
+ nhandles
)
561 /* new input of some other kind */
563 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
565 TranslateMessage (&msg
);
566 DispatchMessage (&msg
);
574 select (0, &rfds
, &wfds
, &xfds
, &tv0
);
576 /* Place a sentinel at the end of the array. */
577 handle_array
[nhandles
] = NULL
;
579 for (i
= 0; i
< nfd
; i
++)
585 if (!(pfd
[i
].events
& (POLLIN
| POLLRDNORM
|
586 POLLOUT
| POLLWRNORM
| POLLWRBAND
)))
589 h
= (HANDLE
) _get_osfhandle (pfd
[i
].fd
);
590 if (h
!= handle_array
[nhandles
])
593 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
594 WSAEventSelect ((SOCKET
) h
, 0, 0);
596 /* If we're lucky, WSAEnumNetworkEvents already provided a way
597 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
598 if (FD_ISSET ((SOCKET
) h
, &rfds
)
599 && !(ev
.lNetworkEvents
& (FD_READ
| FD_ACCEPT
)))
600 ev
.lNetworkEvents
|= FD_READ
| FD_ACCEPT
;
601 if (FD_ISSET ((SOCKET
) h
, &wfds
))
602 ev
.lNetworkEvents
|= FD_WRITE
| FD_CONNECT
;
603 if (FD_ISSET ((SOCKET
) h
, &xfds
))
604 ev
.lNetworkEvents
|= FD_OOB
;
606 happened
= windows_compute_revents_socket ((SOCKET
) h
, pfd
[i
].events
,
612 int sought
= pfd
[i
].events
;
613 happened
= windows_compute_revents (h
, &sought
);
617 if ((pfd
[i
].revents
|= happened
) != 0)
621 if (!rc
&& timeout
== INFTIM
)