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