Mercurial > hg > octave-nkf > gnulib-hg
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; |