1 1.1 christos /* Emulation for select(2) 2 1.1 christos Contributed by Paolo Bonzini. 3 1.1 christos 4 1.1 christos Copyright 2008-2022 Free Software Foundation, Inc. 5 1.1 christos 6 1.1 christos This file is part of gnulib. 7 1.1 christos 8 1.1 christos This file is free software: you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU Lesser General Public License as 10 1.1 christos published by the Free Software Foundation; either version 2.1 of the 11 1.1 christos License, or (at your option) any later version. 12 1.1 christos 13 1.1 christos This file is distributed in the hope that it will be useful, 14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 christos GNU Lesser General Public License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU Lesser General Public License 19 1.1 christos along with this program. If not, see <https://www.gnu.org/licenses/>. */ 20 1.1 christos 21 1.1 christos #include <config.h> 22 1.1 christos 23 1.1 christos /* Specification. */ 24 1.1 christos #include <sys/select.h> 25 1.1 christos 26 1.1 christos #if defined _WIN32 && ! defined __CYGWIN__ 27 1.1 christos /* Native Windows. */ 28 1.1 christos 29 1.1 christos #include <alloca.h> 30 1.1 christos #include <assert.h> 31 1.1 christos #include <sys/types.h> 32 1.1 christos #include <errno.h> 33 1.1 christos #include <limits.h> 34 1.1 christos 35 1.1 christos #include <winsock2.h> 36 1.1 christos #include <windows.h> 37 1.1 christos #include <io.h> 38 1.1 christos #include <stdio.h> 39 1.1 christos #include <conio.h> 40 1.1 christos #include <time.h> 41 1.1 christos 42 1.1 christos /* Get the overridden 'struct timeval'. */ 43 1.1 christos #include <sys/time.h> 44 1.1 christos 45 1.1 christos #if GNULIB_MSVC_NOTHROW 46 1.1 christos # include "msvc-nothrow.h" 47 1.1 christos #else 48 1.1 christos # include <io.h> 49 1.1 christos #endif 50 1.1 christos 51 1.1 christos #undef select 52 1.1 christos 53 1.1 christos /* Don't assume that UNICODE is not defined. */ 54 1.1 christos #undef GetModuleHandle 55 1.1 christos #define GetModuleHandle GetModuleHandleA 56 1.1 christos #undef PeekConsoleInput 57 1.1 christos #define PeekConsoleInput PeekConsoleInputA 58 1.1 christos #undef CreateEvent 59 1.1 christos #define CreateEvent CreateEventA 60 1.1 christos #undef PeekMessage 61 1.1 christos #define PeekMessage PeekMessageA 62 1.1 christos #undef DispatchMessage 63 1.1 christos #define DispatchMessage DispatchMessageA 64 1.1 christos 65 1.1 christos /* Avoid warnings from gcc -Wcast-function-type. */ 66 1.1 christos #define GetProcAddress \ 67 1.1 christos (void *) GetProcAddress 68 1.1 christos 69 1.1 christos struct bitset { 70 1.1 christos unsigned char in[FD_SETSIZE / CHAR_BIT]; 71 1.1 christos unsigned char out[FD_SETSIZE / CHAR_BIT]; 72 1.1 christos }; 73 1.1 christos 74 1.1 christos /* Declare data structures for ntdll functions. */ 75 1.1 christos typedef struct _FILE_PIPE_LOCAL_INFORMATION { 76 1.1 christos ULONG NamedPipeType; 77 1.1 christos ULONG NamedPipeConfiguration; 78 1.1 christos ULONG MaximumInstances; 79 1.1 christos ULONG CurrentInstances; 80 1.1 christos ULONG InboundQuota; 81 1.1 christos ULONG ReadDataAvailable; 82 1.1 christos ULONG OutboundQuota; 83 1.1 christos ULONG WriteQuotaAvailable; 84 1.1 christos ULONG NamedPipeState; 85 1.1 christos ULONG NamedPipeEnd; 86 1.1 christos } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; 87 1.1 christos 88 1.1 christos typedef struct _IO_STATUS_BLOCK 89 1.1 christos { 90 1.1 christos union { 91 1.1 christos DWORD Status; 92 1.1 christos PVOID Pointer; 93 1.1 christos } u; 94 1.1 christos ULONG_PTR Information; 95 1.1 christos } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; 96 1.1 christos 97 1.1 christos typedef enum _FILE_INFORMATION_CLASS { 98 1.1 christos FilePipeLocalInformation = 24 99 1.1 christos } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; 100 1.1 christos 101 1.1 christos typedef DWORD (WINAPI *PNtQueryInformationFile) 102 1.1 christos (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS); 103 1.1 christos 104 1.1 christos #ifndef PIPE_BUF 105 1.1 christos #define PIPE_BUF 512 106 1.1 christos #endif 107 1.1 christos 108 1.1 christos static BOOL IsConsoleHandle (HANDLE h) 109 1.1 christos { 110 1.1 christos DWORD mode; 111 1.1 christos return GetConsoleMode (h, &mode) != 0; 112 1.1 christos } 113 1.1 christos 114 1.1 christos static BOOL 115 1.1 christos IsSocketHandle (HANDLE h) 116 1.1 christos { 117 1.1 christos WSANETWORKEVENTS ev; 118 1.1 christos 119 1.1 christos if (IsConsoleHandle (h)) 120 1.1 christos return FALSE; 121 1.1 christos 122 1.1 christos /* Under Wine, it seems that getsockopt returns 0 for pipes too. 123 1.1 christos WSAEnumNetworkEvents instead distinguishes the two correctly. */ 124 1.1 christos ev.lNetworkEvents = 0xDEADBEEF; 125 1.1 christos WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); 126 1.1 christos return ev.lNetworkEvents != 0xDEADBEEF; 127 1.1 christos } 128 1.1 christos 129 1.1 christos /* Compute output fd_sets for libc descriptor FD (whose Windows handle is 130 1.1 christos H). */ 131 1.1 christos 132 1.1 christos static int 133 1.1 christos windows_poll_handle (HANDLE h, int fd, 134 1.1 christos struct bitset *rbits, 135 1.1 christos struct bitset *wbits, 136 1.1 christos struct bitset *xbits) 137 1.1 christos { 138 1.1 christos BOOL read, write, except; 139 1.1 christos int i, ret; 140 1.1 christos INPUT_RECORD *irbuffer; 141 1.1 christos DWORD avail, nbuffer; 142 1.1 christos BOOL bRet; 143 1.1 christos IO_STATUS_BLOCK iosb; 144 1.1 christos FILE_PIPE_LOCAL_INFORMATION fpli; 145 1.1 christos static PNtQueryInformationFile NtQueryInformationFile; 146 1.1 christos static BOOL once_only; 147 1.1 christos 148 1.1 christos read = write = except = FALSE; 149 1.1 christos switch (GetFileType (h)) 150 1.1 christos { 151 1.1 christos case FILE_TYPE_DISK: 152 1.1 christos read = TRUE; 153 1.1 christos write = TRUE; 154 1.1 christos break; 155 1.1 christos 156 1.1 christos case FILE_TYPE_PIPE: 157 1.1 christos if (!once_only) 158 1.1 christos { 159 1.1 christos NtQueryInformationFile = (PNtQueryInformationFile) 160 1.1 christos GetProcAddress (GetModuleHandle ("ntdll.dll"), 161 1.1 christos "NtQueryInformationFile"); 162 1.1 christos once_only = TRUE; 163 1.1 christos } 164 1.1 christos 165 1.1 christos if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0) 166 1.1 christos { 167 1.1 christos if (avail) 168 1.1 christos read = TRUE; 169 1.1 christos } 170 1.1 christos else if (GetLastError () == ERROR_BROKEN_PIPE) 171 1.1 christos ; 172 1.1 christos 173 1.1 christos else 174 1.1 christos { 175 1.1 christos /* It was the write-end of the pipe. Check if it is writable. 176 1.1 christos If NtQueryInformationFile fails, optimistically assume the pipe is 177 1.1 christos writable. This could happen on Windows 9x, where 178 1.1 christos NtQueryInformationFile is not available, or if we inherit a pipe 179 1.1 christos that doesn't permit FILE_READ_ATTRIBUTES access on the write end 180 1.1 christos (I think this should not happen since Windows XP SP2; WINE seems 181 1.1 christos fine too). Otherwise, ensure that enough space is available for 182 1.1 christos atomic writes. */ 183 1.1 christos memset (&iosb, 0, sizeof (iosb)); 184 1.1 christos memset (&fpli, 0, sizeof (fpli)); 185 1.1 christos 186 1.1 christos if (!NtQueryInformationFile 187 1.1 christos || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli), 188 1.1 christos FilePipeLocalInformation) 189 1.1 christos || fpli.WriteQuotaAvailable >= PIPE_BUF 190 1.1 christos || (fpli.OutboundQuota < PIPE_BUF && 191 1.1 christos fpli.WriteQuotaAvailable == fpli.OutboundQuota)) 192 1.1 christos write = TRUE; 193 1.1 christos } 194 1.1 christos break; 195 1.1 christos 196 1.1 christos case FILE_TYPE_CHAR: 197 1.1 christos write = TRUE; 198 1.1 christos if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1))))) 199 1.1 christos break; 200 1.1 christos 201 1.1 christos ret = WaitForSingleObject (h, 0); 202 1.1 christos if (ret == WAIT_OBJECT_0) 203 1.1 christos { 204 1.1 christos if (!IsConsoleHandle (h)) 205 1.1 christos { 206 1.1 christos read = TRUE; 207 1.1 christos break; 208 1.1 christos } 209 1.1 christos 210 1.1 christos nbuffer = avail = 0; 211 1.1 christos bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); 212 1.1 christos 213 1.1 christos /* Screen buffers handles are filtered earlier. */ 214 1.1 christos assert (bRet); 215 1.1 christos if (nbuffer == 0) 216 1.1 christos { 217 1.1 christos except = TRUE; 218 1.1 christos break; 219 1.1 christos } 220 1.1 christos 221 1.1 christos irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); 222 1.1 christos bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); 223 1.1 christos if (!bRet || avail == 0) 224 1.1 christos { 225 1.1 christos except = TRUE; 226 1.1 christos break; 227 1.1 christos } 228 1.1 christos 229 1.1 christos for (i = 0; i < avail; i++) 230 1.1 christos if (irbuffer[i].EventType == KEY_EVENT) 231 1.1 christos read = TRUE; 232 1.1 christos } 233 1.1 christos break; 234 1.1 christos 235 1.1 christos default: 236 1.1 christos ret = WaitForSingleObject (h, 0); 237 1.1 christos write = TRUE; 238 1.1 christos if (ret == WAIT_OBJECT_0) 239 1.1 christos read = TRUE; 240 1.1 christos 241 1.1 christos break; 242 1.1 christos } 243 1.1 christos 244 1.1 christos ret = 0; 245 1.1 christos if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1))))) 246 1.1 christos { 247 1.1 christos rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1))); 248 1.1 christos ret++; 249 1.1 christos } 250 1.1 christos 251 1.1 christos if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1))))) 252 1.1 christos { 253 1.1 christos wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1))); 254 1.1 christos ret++; 255 1.1 christos } 256 1.1 christos 257 1.1 christos if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1))))) 258 1.1 christos { 259 1.1 christos xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1))); 260 1.1 christos ret++; 261 1.1 christos } 262 1.1 christos 263 1.1 christos return ret; 264 1.1 christos } 265 1.1 christos 266 1.1 christos int 267 1.1 christos rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, 268 1.1 christos struct timeval *timeout) 269 1.1 christos #undef timeval 270 1.1 christos { 271 1.1 christos static struct timeval tv0; 272 1.1 christos static HANDLE hEvent; 273 1.1 christos HANDLE h, handle_array[FD_SETSIZE + 2]; 274 1.1 christos fd_set handle_rfds, handle_wfds, handle_xfds; 275 1.1 christos struct bitset rbits, wbits, xbits; 276 1.1 christos unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT]; 277 1.1 christos DWORD ret, wait_timeout, nhandles, nsock, nbuffer; 278 1.1 christos MSG msg; 279 1.1 christos int i, fd, rc; 280 1.1 christos clock_t tend; 281 1.1 christos 282 1.1 christos if (nfds > FD_SETSIZE) 283 1.1 christos nfds = FD_SETSIZE; 284 1.1 christos 285 1.1 christos if (!timeout) 286 1.1 christos wait_timeout = INFINITE; 287 1.1 christos else 288 1.1 christos { 289 1.1 christos wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; 290 1.1 christos 291 1.1 christos /* select is also used as a portable usleep. */ 292 1.1 christos if (!rfds && !wfds && !xfds) 293 1.1 christos { 294 1.1 christos Sleep (wait_timeout); 295 1.1 christos return 0; 296 1.1 christos } 297 1.1 christos } 298 1.1 christos 299 1.1 christos if (!hEvent) 300 1.1 christos hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); 301 1.1 christos 302 1.1 christos handle_array[0] = hEvent; 303 1.1 christos nhandles = 1; 304 1.1 christos nsock = 0; 305 1.1 christos 306 1.1 christos /* Copy descriptors to bitsets. At the same time, eliminate 307 1.1 christos bits in the "wrong" direction for console input buffers 308 1.1 christos and screen buffers, because screen buffers are waitable 309 1.1 christos and they will block until a character is available. */ 310 1.1 christos memset (&rbits, 0, sizeof (rbits)); 311 1.1 christos memset (&wbits, 0, sizeof (wbits)); 312 1.1 christos memset (&xbits, 0, sizeof (xbits)); 313 1.1 christos memset (anyfds_in, 0, sizeof (anyfds_in)); 314 1.1 christos if (rfds) 315 1.1 christos for (i = 0; i < rfds->fd_count; i++) 316 1.1 christos { 317 1.1 christos fd = rfds->fd_array[i]; 318 1.1 christos h = (HANDLE) _get_osfhandle (fd); 319 1.1 christos if (IsConsoleHandle (h) 320 1.1 christos && !GetNumberOfConsoleInputEvents (h, &nbuffer)) 321 1.1 christos continue; 322 1.1 christos 323 1.1 christos rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 324 1.1 christos anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 325 1.1 christos } 326 1.1 christos else 327 1.1 christos rfds = (fd_set *) alloca (sizeof (fd_set)); 328 1.1 christos 329 1.1 christos if (wfds) 330 1.1 christos for (i = 0; i < wfds->fd_count; i++) 331 1.1 christos { 332 1.1 christos fd = wfds->fd_array[i]; 333 1.1 christos h = (HANDLE) _get_osfhandle (fd); 334 1.1 christos if (IsConsoleHandle (h) 335 1.1 christos && GetNumberOfConsoleInputEvents (h, &nbuffer)) 336 1.1 christos continue; 337 1.1 christos 338 1.1 christos wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 339 1.1 christos anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 340 1.1 christos } 341 1.1 christos else 342 1.1 christos wfds = (fd_set *) alloca (sizeof (fd_set)); 343 1.1 christos 344 1.1 christos if (xfds) 345 1.1 christos for (i = 0; i < xfds->fd_count; i++) 346 1.1 christos { 347 1.1 christos fd = xfds->fd_array[i]; 348 1.1 christos xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 349 1.1 christos anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 350 1.1 christos } 351 1.1 christos else 352 1.1 christos xfds = (fd_set *) alloca (sizeof (fd_set)); 353 1.1 christos 354 1.1 christos /* Zero all the fd_sets, including the application's. */ 355 1.1 christos FD_ZERO (rfds); 356 1.1 christos FD_ZERO (wfds); 357 1.1 christos FD_ZERO (xfds); 358 1.1 christos FD_ZERO (&handle_rfds); 359 1.1 christos FD_ZERO (&handle_wfds); 360 1.1 christos FD_ZERO (&handle_xfds); 361 1.1 christos 362 1.1 christos /* Classify handles. Create fd sets for sockets, poll the others. */ 363 1.1 christos for (i = 0; i < nfds; i++) 364 1.1 christos { 365 1.1 christos if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0) 366 1.1 christos continue; 367 1.1 christos 368 1.1 christos h = (HANDLE) _get_osfhandle (i); 369 1.1 christos if (!h) 370 1.1 christos { 371 1.1 christos errno = EBADF; 372 1.1 christos return -1; 373 1.1 christos } 374 1.1 christos 375 1.1 christos if (IsSocketHandle (h)) 376 1.1 christos { 377 1.1 christos int requested = FD_CLOSE; 378 1.1 christos 379 1.1 christos /* See above; socket handles are mapped onto select, but we 380 1.1 christos need to map descriptors to handles. */ 381 1.1 christos if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 382 1.1 christos { 383 1.1 christos requested |= FD_READ | FD_ACCEPT; 384 1.1 christos FD_SET ((SOCKET) h, rfds); 385 1.1 christos FD_SET ((SOCKET) h, &handle_rfds); 386 1.1 christos } 387 1.1 christos if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 388 1.1 christos { 389 1.1 christos requested |= FD_WRITE | FD_CONNECT; 390 1.1 christos FD_SET ((SOCKET) h, wfds); 391 1.1 christos FD_SET ((SOCKET) h, &handle_wfds); 392 1.1 christos } 393 1.1 christos if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 394 1.1 christos { 395 1.1 christos requested |= FD_OOB; 396 1.1 christos FD_SET ((SOCKET) h, xfds); 397 1.1 christos FD_SET ((SOCKET) h, &handle_xfds); 398 1.1 christos } 399 1.1 christos 400 1.1 christos WSAEventSelect ((SOCKET) h, hEvent, requested); 401 1.1 christos nsock++; 402 1.1 christos } 403 1.1 christos else 404 1.1 christos { 405 1.1 christos handle_array[nhandles++] = h; 406 1.1 christos 407 1.1 christos /* Poll now. If we get an event, do not wait below. */ 408 1.1 christos if (wait_timeout != 0 409 1.1 christos && windows_poll_handle (h, i, &rbits, &wbits, &xbits)) 410 1.1 christos wait_timeout = 0; 411 1.1 christos } 412 1.1 christos } 413 1.1 christos 414 1.1 christos /* Place a sentinel at the end of the array. */ 415 1.1 christos handle_array[nhandles] = NULL; 416 1.1 christos 417 1.1 christos /* When will the waiting period expire? */ 418 1.1 christos if (wait_timeout != INFINITE) 419 1.1 christos tend = clock () + wait_timeout; 420 1.1 christos 421 1.1 christos restart: 422 1.1 christos if (wait_timeout == 0 || nsock == 0) 423 1.1 christos rc = 0; 424 1.1 christos else 425 1.1 christos { 426 1.1 christos /* See if we need to wait in the loop below. If any select is ready, 427 1.1 christos do MsgWaitForMultipleObjects anyway to dispatch messages, but 428 1.1 christos no need to call select again. */ 429 1.1 christos rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0); 430 1.1 christos if (rc == 0) 431 1.1 christos { 432 1.1 christos /* Restore the fd_sets for the other select we do below. */ 433 1.1 christos memcpy (&handle_rfds, rfds, sizeof (fd_set)); 434 1.1 christos memcpy (&handle_wfds, wfds, sizeof (fd_set)); 435 1.1 christos memcpy (&handle_xfds, xfds, sizeof (fd_set)); 436 1.1 christos } 437 1.1 christos else 438 1.1 christos wait_timeout = 0; 439 1.1 christos } 440 1.1 christos 441 1.1 christos /* How much is left to wait? */ 442 1.1 christos if (wait_timeout != INFINITE) 443 1.1 christos { 444 1.1 christos clock_t tnow = clock (); 445 1.1 christos if (tend >= tnow) 446 1.1 christos wait_timeout = tend - tnow; 447 1.1 christos else 448 1.1 christos wait_timeout = 0; 449 1.1 christos } 450 1.1 christos 451 1.1 christos for (;;) 452 1.1 christos { 453 1.1 christos ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE, 454 1.1 christos wait_timeout, QS_ALLINPUT); 455 1.1 christos 456 1.1 christos if (ret == WAIT_OBJECT_0 + nhandles) 457 1.1 christos { 458 1.1 christos /* new input of some other kind */ 459 1.1 christos BOOL bRet; 460 1.1 christos while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0) 461 1.1 christos { 462 1.1 christos TranslateMessage (&msg); 463 1.1 christos DispatchMessage (&msg); 464 1.1 christos } 465 1.1 christos } 466 1.1 christos else 467 1.1 christos break; 468 1.1 christos } 469 1.1 christos 470 1.1 christos /* If we haven't done it yet, check the status of the sockets. */ 471 1.1 christos if (rc == 0 && nsock > 0) 472 1.1 christos rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0); 473 1.1 christos 474 1.1 christos if (nhandles > 1) 475 1.1 christos { 476 1.1 christos /* Count results that are not counted in the return value of select. */ 477 1.1 christos nhandles = 1; 478 1.1 christos for (i = 0; i < nfds; i++) 479 1.1 christos { 480 1.1 christos if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0) 481 1.1 christos continue; 482 1.1 christos 483 1.1 christos h = (HANDLE) _get_osfhandle (i); 484 1.1 christos if (h == handle_array[nhandles]) 485 1.1 christos { 486 1.1 christos /* Not a socket. */ 487 1.1 christos nhandles++; 488 1.1 christos windows_poll_handle (h, i, &rbits, &wbits, &xbits); 489 1.1 christos if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))) 490 1.1 christos || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))) 491 1.1 christos || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 492 1.1 christos rc++; 493 1.1 christos } 494 1.1 christos } 495 1.1 christos 496 1.1 christos if (rc == 0 497 1.1 christos && (wait_timeout == INFINITE 498 1.1 christos /* If NHANDLES > 1, but no bits are set, it means we've 499 1.1 christos been told incorrectly that some handle was signaled. 500 1.1 christos This happens with anonymous pipes, which always cause 501 1.1 christos MsgWaitForMultipleObjects to exit immediately, but no 502 1.1 christos data is found ready to be read by windows_poll_handle. 503 1.1 christos To avoid a total failure (whereby we return zero and 504 1.1 christos don't wait at all), let's poll in a more busy loop. */ 505 1.1 christos || (wait_timeout != 0 && nhandles > 1))) 506 1.1 christos { 507 1.1 christos /* Sleep 1 millisecond to avoid busy wait and retry with the 508 1.1 christos original fd_sets. */ 509 1.1 christos memcpy (&handle_rfds, rfds, sizeof (fd_set)); 510 1.1 christos memcpy (&handle_wfds, wfds, sizeof (fd_set)); 511 1.1 christos memcpy (&handle_xfds, xfds, sizeof (fd_set)); 512 1.1 christos SleepEx (1, TRUE); 513 1.1 christos goto restart; 514 1.1 christos } 515 1.1 christos if (timeout && wait_timeout == 0 && rc == 0) 516 1.1 christos timeout->tv_sec = timeout->tv_usec = 0; 517 1.1 christos } 518 1.1 christos 519 1.1 christos /* Now fill in the results. */ 520 1.1 christos FD_ZERO (rfds); 521 1.1 christos FD_ZERO (wfds); 522 1.1 christos FD_ZERO (xfds); 523 1.1 christos nhandles = 1; 524 1.1 christos for (i = 0; i < nfds; i++) 525 1.1 christos { 526 1.1 christos if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0) 527 1.1 christos continue; 528 1.1 christos 529 1.1 christos h = (HANDLE) _get_osfhandle (i); 530 1.1 christos if (h != handle_array[nhandles]) 531 1.1 christos { 532 1.1 christos /* Perform handle->descriptor mapping. */ 533 1.1 christos SOCKET s = (SOCKET) h; 534 1.1 christos WSAEventSelect (s, NULL, 0); 535 1.1 christos if (FD_ISSET (s, &handle_rfds)) 536 1.1 christos FD_SET (i, rfds); 537 1.1 christos if (FD_ISSET (s, &handle_wfds)) 538 1.1 christos FD_SET (i, wfds); 539 1.1 christos if (FD_ISSET (s, &handle_xfds)) 540 1.1 christos FD_SET (i, xfds); 541 1.1 christos } 542 1.1 christos else 543 1.1 christos { 544 1.1 christos /* Not a socket. */ 545 1.1 christos nhandles++; 546 1.1 christos if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 547 1.1 christos FD_SET (i, rfds); 548 1.1 christos if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 549 1.1 christos FD_SET (i, wfds); 550 1.1 christos if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) 551 1.1 christos FD_SET (i, xfds); 552 1.1 christos } 553 1.1 christos } 554 1.1 christos 555 1.1 christos return rc; 556 1.1 christos } 557 1.1 christos 558 1.1 christos #else /* ! Native Windows. */ 559 1.1 christos 560 1.1 christos #include <stddef.h> /* NULL */ 561 1.1 christos #include <errno.h> 562 1.1 christos #include <unistd.h> 563 1.1 christos 564 1.1 christos #undef select 565 1.1 christos 566 1.1 christos int 567 1.1 christos rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, 568 1.1 christos struct timeval *timeout) 569 1.1 christos { 570 1.1 christos int i; 571 1.1 christos 572 1.1 christos /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */ 573 1.1 christos if (nfds < 0 || nfds > FD_SETSIZE) 574 1.1 christos { 575 1.1 christos errno = EINVAL; 576 1.1 christos return -1; 577 1.1 christos } 578 1.1 christos for (i = 0; i < nfds; i++) 579 1.1 christos { 580 1.1 christos if (((rfds && FD_ISSET (i, rfds)) 581 1.1 christos || (wfds && FD_ISSET (i, wfds)) 582 1.1 christos || (xfds && FD_ISSET (i, xfds))) 583 1.1 christos && dup2 (i, i) != i) 584 1.1 christos return -1; 585 1.1 christos } 586 1.1 christos 587 1.1 christos /* Interix 3.5 has a bug: it does not support nfds == 0. */ 588 1.1 christos if (nfds == 0) 589 1.1 christos { 590 1.1 christos nfds = 1; 591 1.1 christos rfds = NULL; 592 1.1 christos wfds = NULL; 593 1.1 christos xfds = NULL; 594 1.1 christos } 595 1.1 christos return select (nfds, rfds, wfds, xfds, timeout); 596 1.1 christos } 597 1.1 christos 598 1.1 christos #endif 599