poll.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /* Emulation for poll(2)
  2. Contributed by Paolo Bonzini.
  3. Copyright 2001-2003, 2006-2023 Free Software Foundation, Inc.
  4. This file is part of gnulib.
  5. This file is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as
  7. published by the Free Software Foundation; either version 2.1 of the
  8. License, or (at your option) any later version.
  9. This file is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  15. /* Tell gcc not to warn about the (nfd < 0) tests, below. */
  16. #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
  17. # pragma GCC diagnostic ignored "-Wtype-limits"
  18. #endif
  19. #include <config.h>
  20. #include <alloca.h>
  21. #include <sys/types.h>
  22. /* Specification. */
  23. #include <poll.h>
  24. #include <errno.h>
  25. #include <limits.h>
  26. #if defined _WIN32 && ! defined __CYGWIN__
  27. # define WINDOWS_NATIVE
  28. # include <winsock2.h>
  29. # include <windows.h>
  30. # include <io.h>
  31. # include <stdio.h>
  32. # include <conio.h>
  33. # if GNULIB_MSVC_NOTHROW
  34. # include "msvc-nothrow.h"
  35. # else
  36. # include <io.h>
  37. # endif
  38. #else
  39. # include <sys/time.h>
  40. # include <unistd.h>
  41. #endif
  42. #include <sys/select.h>
  43. #include <sys/socket.h>
  44. #ifdef HAVE_SYS_IOCTL_H
  45. # include <sys/ioctl.h>
  46. #endif
  47. #ifdef HAVE_SYS_FILIO_H
  48. # include <sys/filio.h>
  49. #endif
  50. #include <time.h>
  51. #include "assure.h"
  52. #ifndef INFTIM
  53. # define INFTIM (-1)
  54. #endif
  55. /* BeOS does not have MSG_PEEK. */
  56. #ifndef MSG_PEEK
  57. # define MSG_PEEK 0
  58. #endif
  59. #ifdef WINDOWS_NATIVE
  60. /* Don't assume that UNICODE is not defined. */
  61. # undef GetModuleHandle
  62. # define GetModuleHandle GetModuleHandleA
  63. # undef PeekConsoleInput
  64. # define PeekConsoleInput PeekConsoleInputA
  65. # undef CreateEvent
  66. # define CreateEvent CreateEventA
  67. # undef PeekMessage
  68. # define PeekMessage PeekMessageA
  69. # undef DispatchMessage
  70. # define DispatchMessage DispatchMessageA
  71. /* Do *not* use the function WSAPoll
  72. <https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsapoll>
  73. because there is a bug named “Windows 8 Bugs 309411 - WSAPoll does not
  74. report failed connections” that Microsoft won't fix.
  75. See Daniel Stenberg: "WASPoll is broken"
  76. <https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/>. */
  77. /* Here we need the recv() function from Windows, that takes a SOCKET as
  78. first argument, not any possible gnulib override. */
  79. # undef recv
  80. /* Here we need the select() function from Windows, because we pass bit masks
  81. of SOCKETs, not bit masks of FDs. */
  82. # undef select
  83. /* Here we need timeval from Windows since this is what the select() function
  84. from Windows requires. */
  85. # undef timeval
  86. /* Avoid warnings from gcc -Wcast-function-type. */
  87. # define GetProcAddress \
  88. (void *) GetProcAddress
  89. static BOOL IsConsoleHandle (HANDLE h)
  90. {
  91. DWORD mode;
  92. return GetConsoleMode (h, &mode) != 0;
  93. }
  94. static BOOL
  95. IsSocketHandle (HANDLE h)
  96. {
  97. WSANETWORKEVENTS ev;
  98. if (IsConsoleHandle (h))
  99. return FALSE;
  100. /* Under Wine, it seems that getsockopt returns 0 for pipes too.
  101. WSAEnumNetworkEvents instead distinguishes the two correctly. */
  102. ev.lNetworkEvents = 0xDEADBEEF;
  103. WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
  104. return ev.lNetworkEvents != 0xDEADBEEF;
  105. }
  106. /* Declare data structures for ntdll functions. */
  107. typedef struct _FILE_PIPE_LOCAL_INFORMATION {
  108. ULONG NamedPipeType;
  109. ULONG NamedPipeConfiguration;
  110. ULONG MaximumInstances;
  111. ULONG CurrentInstances;
  112. ULONG InboundQuota;
  113. ULONG ReadDataAvailable;
  114. ULONG OutboundQuota;
  115. ULONG WriteQuotaAvailable;
  116. ULONG NamedPipeState;
  117. ULONG NamedPipeEnd;
  118. } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
  119. typedef struct _IO_STATUS_BLOCK
  120. {
  121. union {
  122. DWORD Status;
  123. PVOID Pointer;
  124. } u;
  125. ULONG_PTR Information;
  126. } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
  127. typedef enum _FILE_INFORMATION_CLASS {
  128. FilePipeLocalInformation = 24
  129. } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
  130. typedef DWORD (WINAPI *PNtQueryInformationFile)
  131. (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
  132. # ifndef PIPE_BUF
  133. # define PIPE_BUF 512
  134. # endif
  135. /* Compute revents values for file handle H. If some events cannot happen
  136. for the handle, eliminate them from *P_SOUGHT. */
  137. static int
  138. windows_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. IO_STATUS_BLOCK iosb;
  145. FILE_PIPE_LOCAL_INFORMATION fpli;
  146. static PNtQueryInformationFile NtQueryInformationFile;
  147. static BOOL once_only;
  148. switch (GetFileType (h))
  149. {
  150. case FILE_TYPE_PIPE:
  151. if (!once_only)
  152. {
  153. NtQueryInformationFile = (PNtQueryInformationFile)
  154. GetProcAddress (GetModuleHandle ("ntdll.dll"),
  155. "NtQueryInformationFile");
  156. once_only = TRUE;
  157. }
  158. happened = 0;
  159. if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
  160. {
  161. if (avail)
  162. happened |= *p_sought & (POLLIN | POLLRDNORM);
  163. }
  164. else if (GetLastError () == ERROR_BROKEN_PIPE)
  165. happened |= POLLHUP;
  166. else
  167. {
  168. /* It was the write-end of the pipe. Check if it is writable.
  169. If NtQueryInformationFile fails, optimistically assume the pipe is
  170. writable. This could happen on Windows 9x, where
  171. NtQueryInformationFile is not available, or if we inherit a pipe
  172. that doesn't permit FILE_READ_ATTRIBUTES access on the write end
  173. (I think this should not happen since Windows XP SP2; WINE seems
  174. fine too). Otherwise, ensure that enough space is available for
  175. atomic writes. */
  176. memset (&iosb, 0, sizeof (iosb));
  177. memset (&fpli, 0, sizeof (fpli));
  178. if (!NtQueryInformationFile
  179. || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
  180. FilePipeLocalInformation)
  181. || fpli.WriteQuotaAvailable >= PIPE_BUF
  182. || (fpli.OutboundQuota < PIPE_BUF &&
  183. fpli.WriteQuotaAvailable == fpli.OutboundQuota))
  184. happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
  185. }
  186. return happened;
  187. case FILE_TYPE_CHAR:
  188. ret = WaitForSingleObject (h, 0);
  189. if (!IsConsoleHandle (h))
  190. return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
  191. nbuffer = avail = 0;
  192. bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
  193. if (bRet)
  194. {
  195. /* Input buffer. */
  196. *p_sought &= POLLIN | POLLRDNORM;
  197. if (nbuffer == 0)
  198. return POLLHUP;
  199. if (!*p_sought)
  200. return 0;
  201. irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
  202. bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
  203. if (!bRet || avail == 0)
  204. return POLLHUP;
  205. for (i = 0; i < avail; i++)
  206. if (irbuffer[i].EventType == KEY_EVENT)
  207. return *p_sought;
  208. return 0;
  209. }
  210. else
  211. {
  212. /* Screen buffer. */
  213. *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
  214. return *p_sought;
  215. }
  216. default:
  217. ret = WaitForSingleObject (h, 0);
  218. if (ret == WAIT_OBJECT_0)
  219. return *p_sought & ~(POLLPRI | POLLRDBAND);
  220. return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
  221. }
  222. }
  223. /* Convert fd_sets returned by select into revents values. */
  224. static int
  225. windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
  226. {
  227. int happened = 0;
  228. if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
  229. happened |= (POLLIN | POLLRDNORM) & sought;
  230. else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
  231. {
  232. int r, error;
  233. char data[64];
  234. WSASetLastError (0);
  235. r = recv (h, data, sizeof (data), MSG_PEEK);
  236. error = WSAGetLastError ();
  237. WSASetLastError (0);
  238. if (r > 0 || error == WSAENOTCONN)
  239. happened |= (POLLIN | POLLRDNORM) & sought;
  240. /* Distinguish hung-up sockets from other errors. */
  241. else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
  242. || error == WSAECONNABORTED || error == WSAENETRESET)
  243. happened |= POLLHUP;
  244. else
  245. happened |= POLLERR;
  246. }
  247. if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
  248. happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
  249. if (lNetworkEvents & FD_OOB)
  250. happened |= (POLLPRI | POLLRDBAND) & sought;
  251. return happened;
  252. }
  253. #else /* !MinGW */
  254. /* Convert select(2) returned fd_sets into poll(2) revents values. */
  255. static int
  256. compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
  257. {
  258. int happened = 0;
  259. if (FD_ISSET (fd, rfds))
  260. {
  261. int r;
  262. int socket_errno;
  263. # if defined __MACH__ && defined __APPLE__
  264. /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
  265. for some kinds of descriptors. Detect if this descriptor is a
  266. connected socket, a server socket, or something else using a
  267. 0-byte recv, and use ioctl(2) to detect POLLHUP. */
  268. r = recv (fd, NULL, 0, MSG_PEEK);
  269. socket_errno = (r < 0) ? errno : 0;
  270. if (r == 0 || socket_errno == ENOTSOCK)
  271. ioctl (fd, FIONREAD, &r);
  272. # else
  273. char data[64];
  274. r = recv (fd, data, sizeof (data), MSG_PEEK);
  275. socket_errno = (r < 0) ? errno : 0;
  276. # endif
  277. if (r == 0)
  278. happened |= POLLHUP;
  279. /* If the event happened on an unconnected server socket,
  280. that's fine. */
  281. else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
  282. happened |= (POLLIN | POLLRDNORM) & sought;
  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. /* some systems can't use recv() on non-socket, including HP NonStop */
  288. else if (socket_errno == ENOTSOCK)
  289. happened |= (POLLIN | POLLRDNORM) & sought;
  290. else
  291. happened |= POLLERR;
  292. }
  293. if (FD_ISSET (fd, wfds))
  294. happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
  295. if (FD_ISSET (fd, efds))
  296. happened |= (POLLPRI | POLLRDBAND) & sought;
  297. return happened;
  298. }
  299. #endif /* !MinGW */
  300. int
  301. poll (struct pollfd *pfd, nfds_t nfd, int timeout)
  302. {
  303. #ifndef WINDOWS_NATIVE
  304. fd_set rfds, wfds, efds;
  305. struct timeval tv;
  306. struct timeval *ptv;
  307. int maxfd, rc;
  308. nfds_t i;
  309. if (nfd > INT_MAX)
  310. {
  311. errno = EINVAL;
  312. return -1;
  313. }
  314. /* Don't check directly for NFD greater than OPEN_MAX. Any practical use
  315. of a too-large NFD is caught by one of the other checks below, and
  316. checking directly for getdtablesize is too much of a portability
  317. and/or performance and/or correctness hassle. */
  318. /* EFAULT is not necessary to implement, but let's do it in the
  319. simplest case. */
  320. if (!pfd && nfd)
  321. {
  322. errno = EFAULT;
  323. return -1;
  324. }
  325. /* convert timeout number into a timeval structure */
  326. if (timeout == 0)
  327. {
  328. ptv = &tv;
  329. ptv->tv_sec = 0;
  330. ptv->tv_usec = 0;
  331. }
  332. else if (timeout > 0)
  333. {
  334. ptv = &tv;
  335. ptv->tv_sec = timeout / 1000;
  336. ptv->tv_usec = (timeout % 1000) * 1000;
  337. }
  338. else if (timeout == INFTIM)
  339. /* wait forever */
  340. ptv = NULL;
  341. else
  342. {
  343. errno = EINVAL;
  344. return -1;
  345. }
  346. /* create fd sets and determine max fd */
  347. maxfd = -1;
  348. FD_ZERO (&rfds);
  349. FD_ZERO (&wfds);
  350. FD_ZERO (&efds);
  351. for (i = 0; i < nfd; i++)
  352. {
  353. if (pfd[i].fd < 0)
  354. continue;
  355. if (maxfd < pfd[i].fd)
  356. {
  357. maxfd = pfd[i].fd;
  358. if (FD_SETSIZE <= maxfd)
  359. {
  360. errno = EINVAL;
  361. return -1;
  362. }
  363. }
  364. if (pfd[i].events & (POLLIN | POLLRDNORM))
  365. FD_SET (pfd[i].fd, &rfds);
  366. /* see select(2): "the only exceptional condition detectable
  367. is out-of-band data received on a socket", hence we push
  368. POLLWRBAND events onto wfds instead of efds. */
  369. if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
  370. FD_SET (pfd[i].fd, &wfds);
  371. if (pfd[i].events & (POLLPRI | POLLRDBAND))
  372. FD_SET (pfd[i].fd, &efds);
  373. }
  374. /* examine fd sets */
  375. rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
  376. if (rc < 0)
  377. return rc;
  378. /* establish results */
  379. rc = 0;
  380. for (i = 0; i < nfd; i++)
  381. {
  382. pfd[i].revents = (pfd[i].fd < 0
  383. ? 0
  384. : compute_revents (pfd[i].fd, pfd[i].events,
  385. &rfds, &wfds, &efds));
  386. rc += pfd[i].revents != 0;
  387. }
  388. return rc;
  389. #else
  390. static struct timeval tv0;
  391. static HANDLE hEvent;
  392. WSANETWORKEVENTS ev;
  393. HANDLE h, handle_array[FD_SETSIZE + 2];
  394. DWORD ret, wait_timeout, nhandles;
  395. fd_set rfds, wfds, xfds;
  396. BOOL poll_again;
  397. MSG msg;
  398. int rc = 0;
  399. nfds_t i;
  400. if (nfd > INT_MAX || timeout < -1)
  401. {
  402. errno = EINVAL;
  403. return -1;
  404. }
  405. if (!hEvent)
  406. hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  407. restart:
  408. handle_array[0] = hEvent;
  409. nhandles = 1;
  410. FD_ZERO (&rfds);
  411. FD_ZERO (&wfds);
  412. FD_ZERO (&xfds);
  413. /* Classify socket handles and create fd sets. */
  414. for (i = 0; i < nfd; i++)
  415. {
  416. int sought = pfd[i].events;
  417. pfd[i].revents = 0;
  418. if (pfd[i].fd < 0)
  419. continue;
  420. if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
  421. | POLLPRI | POLLRDBAND)))
  422. continue;
  423. h = (HANDLE) _get_osfhandle (pfd[i].fd);
  424. assure (h != NULL);
  425. if (IsSocketHandle (h))
  426. {
  427. int requested = FD_CLOSE;
  428. /* see above; socket handles are mapped onto select. */
  429. if (sought & (POLLIN | POLLRDNORM))
  430. {
  431. requested |= FD_READ | FD_ACCEPT;
  432. FD_SET ((SOCKET) h, &rfds);
  433. }
  434. if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
  435. {
  436. requested |= FD_WRITE | FD_CONNECT;
  437. FD_SET ((SOCKET) h, &wfds);
  438. }
  439. if (sought & (POLLPRI | POLLRDBAND))
  440. {
  441. requested |= FD_OOB;
  442. FD_SET ((SOCKET) h, &xfds);
  443. }
  444. if (requested)
  445. WSAEventSelect ((SOCKET) h, hEvent, requested);
  446. }
  447. else
  448. {
  449. /* Poll now. If we get an event, do not poll again. Also,
  450. screen buffer handles are waitable, and they'll block until
  451. a character is available. windows_compute_revents eliminates
  452. bits for the "wrong" direction. */
  453. pfd[i].revents = windows_compute_revents (h, &sought);
  454. if (sought)
  455. handle_array[nhandles++] = h;
  456. if (pfd[i].revents)
  457. timeout = 0;
  458. }
  459. }
  460. if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
  461. {
  462. /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
  463. no need to call select again. */
  464. poll_again = FALSE;
  465. wait_timeout = 0;
  466. }
  467. else
  468. {
  469. poll_again = TRUE;
  470. if (timeout == INFTIM)
  471. wait_timeout = INFINITE;
  472. else
  473. wait_timeout = timeout;
  474. }
  475. for (;;)
  476. {
  477. ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
  478. wait_timeout, QS_ALLINPUT);
  479. if (ret == WAIT_OBJECT_0 + nhandles)
  480. {
  481. /* new input of some other kind */
  482. BOOL bRet;
  483. while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
  484. {
  485. TranslateMessage (&msg);
  486. DispatchMessage (&msg);
  487. }
  488. }
  489. else
  490. break;
  491. }
  492. if (poll_again)
  493. select (0, &rfds, &wfds, &xfds, &tv0);
  494. /* Place a sentinel at the end of the array. */
  495. handle_array[nhandles] = NULL;
  496. nhandles = 1;
  497. for (i = 0; i < nfd; i++)
  498. {
  499. int happened;
  500. if (pfd[i].fd < 0)
  501. continue;
  502. if (!(pfd[i].events & (POLLIN | POLLRDNORM |
  503. POLLOUT | POLLWRNORM | POLLWRBAND)))
  504. continue;
  505. h = (HANDLE) _get_osfhandle (pfd[i].fd);
  506. if (h != handle_array[nhandles])
  507. {
  508. /* It's a socket. */
  509. WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
  510. WSAEventSelect ((SOCKET) h, 0, 0);
  511. /* If we're lucky, WSAEnumNetworkEvents already provided a way
  512. to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
  513. if (FD_ISSET ((SOCKET) h, &rfds)
  514. && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
  515. ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
  516. if (FD_ISSET ((SOCKET) h, &wfds))
  517. ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
  518. if (FD_ISSET ((SOCKET) h, &xfds))
  519. ev.lNetworkEvents |= FD_OOB;
  520. happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
  521. ev.lNetworkEvents);
  522. }
  523. else
  524. {
  525. /* Not a socket. */
  526. int sought = pfd[i].events;
  527. happened = windows_compute_revents (h, &sought);
  528. nhandles++;
  529. }
  530. if ((pfd[i].revents |= happened) != 0)
  531. rc++;
  532. }
  533. if (!rc && timeout == INFTIM)
  534. {
  535. SleepEx (1, TRUE);
  536. goto restart;
  537. }
  538. return rc;
  539. #endif
  540. }