comparison lib/poll.c @ 17924:68876b89b3ad

poll: fixes for large fds * lib/poll.c (poll): Don't check directly for NFD too large. Don't rely on undefined behavior in FD_SET when an arg exceeds FD_SETSIZE. Always set revents afterwards, even if to zero. * tests/test-poll.c (poll1): Set revents to -1 instead of 0, as that makes the test a bit stricter.
author Paul Eggert <eggert@cs.ucla.edu>
date Fri, 20 Feb 2015 10:37:49 -0800
parents ab58d4870664
children
comparison
equal deleted inserted replaced
17923:2b5c3699ac6f 17924:68876b89b3ad
332 struct timeval tv; 332 struct timeval tv;
333 struct timeval *ptv; 333 struct timeval *ptv;
334 int maxfd, rc; 334 int maxfd, rc;
335 nfds_t i; 335 nfds_t i;
336 336
337 # ifdef _SC_OPEN_MAX 337 if (nfd < 0)
338 static int sc_open_max = -1;
339
340 if (nfd < 0
341 || (nfd > sc_open_max
342 && (sc_open_max != -1
343 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
344 { 338 {
345 errno = EINVAL; 339 errno = EINVAL;
346 return -1; 340 return -1;
347 } 341 }
348 # else /* !_SC_OPEN_MAX */ 342 /* Don't check directly for NFD too large. Any practical use of a
349 # ifdef OPEN_MAX 343 too-large NFD is caught by one of the other checks below, and
350 if (nfd < 0 || nfd > OPEN_MAX) 344 checking directly for getdtablesize is too much of a portability
351 { 345 and/or performance and/or correctness hassle. */
352 errno = EINVAL;
353 return -1;
354 }
355 # endif /* OPEN_MAX -- else, no check is needed */
356 # endif /* !_SC_OPEN_MAX */
357 346
358 /* EFAULT is not necessary to implement, but let's do it in the 347 /* EFAULT is not necessary to implement, but let's do it in the
359 simplest case. */ 348 simplest case. */
360 if (!pfd && nfd) 349 if (!pfd && nfd)
361 { 350 {
392 FD_ZERO (&efds); 381 FD_ZERO (&efds);
393 for (i = 0; i < nfd; i++) 382 for (i = 0; i < nfd; i++)
394 { 383 {
395 if (pfd[i].fd < 0) 384 if (pfd[i].fd < 0)
396 continue; 385 continue;
397 386 if (maxfd < pfd[i].fd)
387 {
388 maxfd = pfd[i].fd;
389 if (FD_SETSIZE <= maxfd)
390 {
391 errno = EINVAL;
392 return -1;
393 }
394 }
398 if (pfd[i].events & (POLLIN | POLLRDNORM)) 395 if (pfd[i].events & (POLLIN | POLLRDNORM))
399 FD_SET (pfd[i].fd, &rfds); 396 FD_SET (pfd[i].fd, &rfds);
400
401 /* see select(2): "the only exceptional condition detectable 397 /* see select(2): "the only exceptional condition detectable
402 is out-of-band data received on a socket", hence we push 398 is out-of-band data received on a socket", hence we push
403 POLLWRBAND events onto wfds instead of efds. */ 399 POLLWRBAND events onto wfds instead of efds. */
404 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) 400 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
405 FD_SET (pfd[i].fd, &wfds); 401 FD_SET (pfd[i].fd, &wfds);
406 if (pfd[i].events & (POLLPRI | POLLRDBAND)) 402 if (pfd[i].events & (POLLPRI | POLLRDBAND))
407 FD_SET (pfd[i].fd, &efds); 403 FD_SET (pfd[i].fd, &efds);
408 if (pfd[i].fd >= maxfd
409 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
410 | POLLRDNORM | POLLRDBAND
411 | POLLWRNORM | POLLWRBAND)))
412 {
413 maxfd = pfd[i].fd;
414 if (maxfd > FD_SETSIZE)
415 {
416 errno = EOVERFLOW;
417 return -1;
418 }
419 }
420 } 404 }
421 405
422 /* examine fd sets */ 406 /* examine fd sets */
423 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv); 407 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
424 if (rc < 0) 408 if (rc < 0)
425 return rc; 409 return rc;
426 410
427 /* establish results */ 411 /* establish results */
428 rc = 0; 412 rc = 0;
429 for (i = 0; i < nfd; i++) 413 for (i = 0; i < nfd; i++)
430 if (pfd[i].fd < 0) 414 {
431 pfd[i].revents = 0; 415 pfd[i].revents = (pfd[i].fd < 0
432 else 416 ? 0
433 { 417 : compute_revents (pfd[i].fd, pfd[i].events,
434 int happened = compute_revents (pfd[i].fd, pfd[i].events, 418 &rfds, &wfds, &efds));
435 &rfds, &wfds, &efds); 419 rc += pfd[i].revents != 0;
436 if (happened) 420 }
437 {
438 pfd[i].revents = happened;
439 rc++;
440 }
441 }
442 421
443 return rc; 422 return rc;
444 #else 423 #else
445 static struct timeval tv0; 424 static struct timeval tv0;
446 static HANDLE hEvent; 425 static HANDLE hEvent;