Git fork
1/* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
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)
11 any later version.
12
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.
17
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/>. */
20
21#define DISABLE_SIGN_COMPARE_WARNINGS
22
23/* To bump the minimum Windows version to Windows Vista */
24#include "git-compat-util.h"
25
26/* Tell gcc not to warn about the (nfd < 0) tests, below. */
27#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
28# pragma GCC diagnostic ignored "-Wtype-limits"
29#endif
30
31#if defined(WIN32)
32# include <malloc.h>
33#endif
34
35#include <sys/types.h>
36
37#include <errno.h>
38#include <limits.h>
39#include <assert.h>
40
41#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
42# define WIN32_NATIVE
43# if defined (_MSC_VER) && !defined(_WIN32_WINNT)
44# define _WIN32_WINNT 0x0502
45# endif
46# include <winsock2.h>
47# include <windows.h>
48# include <io.h>
49# include <stdio.h>
50# include <conio.h>
51#else
52# include <sys/time.h>
53# include <sys/socket.h>
54# ifndef NO_SYS_SELECT_H
55# include <sys/select.h>
56# endif
57# include <unistd.h>
58#endif
59
60/* Specification. */
61#include "poll.h"
62
63#ifdef HAVE_SYS_IOCTL_H
64# include <sys/ioctl.h>
65#endif
66#ifdef HAVE_SYS_FILIO_H
67# include <sys/filio.h>
68#endif
69
70#include <time.h>
71
72#ifndef INFTIM
73# define INFTIM (-1)
74#endif
75
76/* BeOS does not have MSG_PEEK. */
77#ifndef MSG_PEEK
78# define MSG_PEEK 0
79#endif
80
81#ifdef WIN32_NATIVE
82
83#define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
84
85static BOOL
86IsSocketHandle (HANDLE h)
87{
88 WSANETWORKEVENTS ev;
89
90 if (IsConsoleHandle (h))
91 return FALSE;
92
93 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
94 WSAEnumNetworkEvents instead distinguishes the two correctly. */
95 ev.lNetworkEvents = 0xDEADBEEF;
96 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
97 return ev.lNetworkEvents != 0xDEADBEEF;
98}
99
100/* Declare data structures for ntdll functions. */
101typedef struct _FILE_PIPE_LOCAL_INFORMATION {
102 ULONG NamedPipeType;
103 ULONG NamedPipeConfiguration;
104 ULONG MaximumInstances;
105 ULONG CurrentInstances;
106 ULONG InboundQuota;
107 ULONG ReadDataAvailable;
108 ULONG OutboundQuota;
109 ULONG WriteQuotaAvailable;
110 ULONG NamedPipeState;
111 ULONG NamedPipeEnd;
112} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
113
114typedef struct _IO_STATUS_BLOCK
115{
116 union {
117 DWORD Status;
118 PVOID Pointer;
119 } u;
120 ULONG_PTR Information;
121} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
122
123typedef enum _FILE_INFORMATION_CLASS {
124 FilePipeLocalInformation = 24
125} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
126
127typedef DWORD (WINAPI *PNtQueryInformationFile)
128 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
129
130# ifndef PIPE_BUF
131# define PIPE_BUF 512
132# endif
133
134/* Compute revents values for file handle H. If some events cannot happen
135 for the handle, eliminate them from *P_SOUGHT. */
136
137static int
138win32_compute_revents (HANDLE h, int *p_sought)
139{
140 int i, ret, happened;
141 INPUT_RECORD *irbuffer;
142 DWORD avail, nbuffer;
143 BOOL bRet;
144
145 switch (GetFileType (h))
146 {
147 case FILE_TYPE_PIPE:
148 happened = 0;
149 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
150 {
151 if (avail)
152 happened |= *p_sought & (POLLIN | POLLRDNORM);
153 }
154 else if (GetLastError () == ERROR_BROKEN_PIPE)
155 happened |= POLLHUP;
156
157 else
158 {
159 /* It was the write-end of the pipe. Unfortunately there is no
160 reliable way of knowing if it can be written without blocking.
161 Just say that it's all good. */
162 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
163 }
164 return happened;
165
166 case FILE_TYPE_CHAR:
167 ret = WaitForSingleObject (h, 0);
168 if (!IsConsoleHandle (h))
169 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
170
171 nbuffer = avail = 0;
172 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
173 if (bRet)
174 {
175 /* Input buffer. */
176 *p_sought &= POLLIN | POLLRDNORM;
177 if (nbuffer == 0)
178 return POLLHUP;
179 if (!*p_sought)
180 return 0;
181
182 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
183 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
184 if (!bRet || avail == 0)
185 return POLLHUP;
186
187 for (i = 0; i < avail; i++)
188 if (irbuffer[i].EventType == KEY_EVENT)
189 return *p_sought;
190 return 0;
191 }
192 else
193 {
194 /* Screen buffer. */
195 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
196 return *p_sought;
197 }
198
199 default:
200 ret = WaitForSingleObject (h, 0);
201 if (ret == WAIT_OBJECT_0)
202 return *p_sought & ~(POLLPRI | POLLRDBAND);
203
204 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
205 }
206}
207
208/* Convert fd_sets returned by select into revents values. */
209
210static int
211win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
212{
213 int happened = 0;
214
215 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
216 happened |= (POLLIN | POLLRDNORM) & sought;
217
218 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
219 {
220 int r, error;
221
222 char data[64];
223 WSASetLastError (0);
224 r = recv (h, data, sizeof (data), MSG_PEEK);
225 error = WSAGetLastError ();
226 WSASetLastError (0);
227
228 if (r > 0 || error == WSAENOTCONN)
229 happened |= (POLLIN | POLLRDNORM) & sought;
230
231 /* Distinguish hung-up sockets from other errors. */
232 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
233 || error == WSAECONNABORTED || error == WSAENETRESET)
234 happened |= POLLHUP;
235
236 else
237 happened |= POLLERR;
238 }
239
240 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
241 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
242
243 if (lNetworkEvents & FD_OOB)
244 happened |= (POLLPRI | POLLRDBAND) & sought;
245
246 return happened;
247}
248
249#else /* !MinGW */
250
251/* Convert select(2) returned fd_sets into poll(2) revents values. */
252static int
253compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
254{
255 int happened = 0;
256 if (FD_ISSET (fd, rfds))
257 {
258 int r;
259 int socket_errno;
260
261# if defined __MACH__ && defined __APPLE__
262 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
263 for some kinds of descriptors. Detect if this descriptor is a
264 connected socket, a server socket, or something else using a
265 0-byte recv, and use ioctl(2) to detect POLLHUP. */
266 r = recv (fd, NULL, 0, MSG_PEEK);
267 socket_errno = (r < 0) ? errno : 0;
268 if (r == 0 || socket_errno == ENOTSOCK)
269 ioctl (fd, FIONREAD, &r);
270# else
271 char data[64];
272 r = recv (fd, data, sizeof (data), MSG_PEEK);
273 socket_errno = (r < 0) ? errno : 0;
274# endif
275 if (r == 0)
276 happened |= POLLHUP;
277
278 /* If the event happened on an unconnected server socket,
279 that's fine. */
280 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
281 happened |= (POLLIN | POLLRDNORM) & sought;
282
283 /* Distinguish hung-up sockets from other errors. */
284 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
285 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
286 happened |= POLLHUP;
287
288 /* some systems can't use recv() on non-socket, including HP NonStop */
289 else if (/* (r == -1) && */ socket_errno == ENOTSOCK)
290 happened |= (POLLIN | POLLRDNORM) & sought;
291
292 else
293 happened |= POLLERR;
294 }
295
296 if (FD_ISSET (fd, wfds))
297 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
298
299 if (FD_ISSET (fd, efds))
300 happened |= (POLLPRI | POLLRDBAND) & sought;
301
302 return happened;
303}
304#endif /* !MinGW */
305
306int
307poll (struct pollfd *pfd, nfds_t nfd, int timeout)
308{
309#ifndef WIN32_NATIVE
310 fd_set rfds, wfds, efds;
311 struct timeval tv;
312 struct timeval *ptv;
313 int maxfd, rc;
314 nfds_t i;
315
316# ifdef _SC_OPEN_MAX
317 static int sc_open_max = -1;
318
319 if (nfd < 0
320 || (nfd > sc_open_max
321 && (sc_open_max != -1
322 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
323 {
324 errno = EINVAL;
325 return -1;
326 }
327# else /* !_SC_OPEN_MAX */
328# ifdef OPEN_MAX
329 if (nfd < 0 || nfd > OPEN_MAX)
330 {
331 errno = EINVAL;
332 return -1;
333 }
334# endif /* OPEN_MAX -- else, no check is needed */
335# endif /* !_SC_OPEN_MAX */
336
337 /* EFAULT is not necessary to implement, but let's do it in the
338 simplest case. */
339 if (!pfd && nfd)
340 {
341 errno = EFAULT;
342 return -1;
343 }
344
345 /* convert timeout number into a timeval structure */
346 if (timeout == 0)
347 {
348 ptv = &tv;
349 ptv->tv_sec = 0;
350 ptv->tv_usec = 0;
351 }
352 else if (timeout > 0)
353 {
354 ptv = &tv;
355 ptv->tv_sec = timeout / 1000;
356 ptv->tv_usec = (timeout % 1000) * 1000;
357 }
358 else if (timeout == INFTIM)
359 /* wait forever */
360 ptv = NULL;
361 else
362 {
363 errno = EINVAL;
364 return -1;
365 }
366
367 /* create fd sets and determine max fd */
368 maxfd = -1;
369 FD_ZERO (&rfds);
370 FD_ZERO (&wfds);
371 FD_ZERO (&efds);
372 for (i = 0; i < nfd; i++)
373 {
374 if (pfd[i].fd < 0)
375 continue;
376
377 if (pfd[i].events & (POLLIN | POLLRDNORM))
378 FD_SET (pfd[i].fd, &rfds);
379
380 /* see select(2): "the only exceptional condition detectable
381 is out-of-band data received on a socket", hence we push
382 POLLWRBAND events onto wfds instead of efds. */
383 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
384 FD_SET (pfd[i].fd, &wfds);
385 if (pfd[i].events & (POLLPRI | POLLRDBAND))
386 FD_SET (pfd[i].fd, &efds);
387 if (pfd[i].fd >= maxfd
388 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
389 | POLLRDNORM | POLLRDBAND
390 | POLLWRNORM | POLLWRBAND)))
391 {
392 maxfd = pfd[i].fd;
393 if (maxfd > FD_SETSIZE)
394 {
395 errno = EOVERFLOW;
396 return -1;
397 }
398 }
399 }
400
401 /* examine fd sets */
402 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
403 if (rc < 0)
404 return rc;
405
406 /* establish results */
407 rc = 0;
408 for (i = 0; i < nfd; i++)
409 if (pfd[i].fd < 0)
410 pfd[i].revents = 0;
411 else
412 {
413 int happened = compute_revents (pfd[i].fd, pfd[i].events,
414 &rfds, &wfds, &efds);
415 if (happened)
416 {
417 pfd[i].revents = happened;
418 rc++;
419 }
420 else
421 {
422 pfd[i].revents = 0;
423 }
424 }
425
426 return rc;
427#else
428 static struct timeval tv0;
429 static HANDLE hEvent;
430 WSANETWORKEVENTS ev;
431 HANDLE h, handle_array[FD_SETSIZE + 2];
432 DWORD ret, wait_timeout, nhandles, orig_timeout = 0;
433 ULONGLONG start = 0;
434 fd_set rfds, wfds, xfds;
435 BOOL poll_again;
436 MSG msg;
437 int rc = 0;
438 nfds_t i;
439
440 if (nfd < 0 || timeout < -1)
441 {
442 errno = EINVAL;
443 return -1;
444 }
445
446 if (timeout != INFTIM)
447 {
448 orig_timeout = timeout;
449 start = GetTickCount64();
450 }
451
452 if (!hEvent)
453 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
454
455restart:
456 handle_array[0] = hEvent;
457 nhandles = 1;
458 FD_ZERO (&rfds);
459 FD_ZERO (&wfds);
460 FD_ZERO (&xfds);
461
462 /* Classify socket handles and create fd sets. */
463 for (i = 0; i < nfd; i++)
464 {
465 int sought = pfd[i].events;
466 pfd[i].revents = 0;
467 if (pfd[i].fd < 0)
468 continue;
469 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
470 | POLLPRI | POLLRDBAND)))
471 continue;
472
473 h = (HANDLE) _get_osfhandle (pfd[i].fd);
474 assert (h != NULL);
475 if (IsSocketHandle (h))
476 {
477 int requested = FD_CLOSE;
478
479 /* see above; socket handles are mapped onto select. */
480 if (sought & (POLLIN | POLLRDNORM))
481 {
482 requested |= FD_READ | FD_ACCEPT;
483 FD_SET ((SOCKET) h, &rfds);
484 }
485 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
486 {
487 requested |= FD_WRITE | FD_CONNECT;
488 FD_SET ((SOCKET) h, &wfds);
489 }
490 if (sought & (POLLPRI | POLLRDBAND))
491 {
492 requested |= FD_OOB;
493 FD_SET ((SOCKET) h, &xfds);
494 }
495
496 if (requested)
497 WSAEventSelect ((SOCKET) h, hEvent, requested);
498 }
499 else
500 {
501 /* Poll now. If we get an event, do not poll again. Also,
502 screen buffer handles are waitable, and they'll block until
503 a character is available. win32_compute_revents eliminates
504 bits for the "wrong" direction. */
505 pfd[i].revents = win32_compute_revents (h, &sought);
506 if (sought)
507 handle_array[nhandles++] = h;
508 if (pfd[i].revents)
509 timeout = 0;
510 }
511 }
512
513 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
514 {
515 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
516 no need to call select again. */
517 poll_again = FALSE;
518 wait_timeout = 0;
519 }
520 else
521 {
522 poll_again = TRUE;
523 if (timeout == INFTIM)
524 wait_timeout = INFINITE;
525 else
526 wait_timeout = timeout;
527 }
528
529 for (;;)
530 {
531 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
532 wait_timeout, QS_ALLINPUT);
533
534 if (ret == WAIT_OBJECT_0 + nhandles)
535 {
536 /* new input of some other kind */
537 BOOL bRet;
538 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
539 {
540 TranslateMessage (&msg);
541 DispatchMessage (&msg);
542 }
543 }
544 else
545 break;
546 }
547
548 if (poll_again)
549 select (0, &rfds, &wfds, &xfds, &tv0);
550
551 /* Place a sentinel at the end of the array. */
552 handle_array[nhandles] = NULL;
553 nhandles = 1;
554 for (i = 0; i < nfd; i++)
555 {
556 int happened;
557
558 if (pfd[i].fd < 0)
559 continue;
560 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
561 POLLOUT | POLLWRNORM | POLLWRBAND)))
562 continue;
563
564 h = (HANDLE) _get_osfhandle (pfd[i].fd);
565 if (h != handle_array[nhandles])
566 {
567 /* It's a socket. */
568 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
569 WSAEventSelect ((SOCKET) h, NULL, 0);
570
571 /* If we're lucky, WSAEnumNetworkEvents already provided a way
572 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
573 if (FD_ISSET ((SOCKET) h, &rfds)
574 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
575 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
576 if (FD_ISSET ((SOCKET) h, &wfds))
577 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
578 if (FD_ISSET ((SOCKET) h, &xfds))
579 ev.lNetworkEvents |= FD_OOB;
580
581 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
582 ev.lNetworkEvents);
583 }
584 else
585 {
586 /* Not a socket. */
587 int sought = pfd[i].events;
588 happened = win32_compute_revents (h, &sought);
589 nhandles++;
590 }
591
592 if ((pfd[i].revents |= happened) != 0)
593 rc++;
594 }
595
596 if (!rc && orig_timeout && timeout != INFTIM)
597 {
598 ULONGLONG elapsed = GetTickCount64() - start;
599 timeout = elapsed >= orig_timeout ? 0 : (int)(orig_timeout - elapsed);
600 }
601
602 if (!rc && timeout)
603 {
604 SleepEx (1, TRUE);
605 goto restart;
606 }
607
608 return rc;
609#endif
610}