123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- /* pselect - synchronous I/O multiplexing
- Copyright 2011-2015 Free Software Foundation, Inc.
- This file is part of gnulib.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <http://www.gnu.org/licenses/>. */
- /* written by Paul Eggert */
- #include <config.h>
- #include <sys/select.h>
- #include <errno.h>
- #include <signal.h>
- /* Examine the size-NFDS file descriptor sets in RFDS, WFDS, and XFDS
- to see whether some of their descriptors are ready for reading,
- ready for writing, or have exceptions pending. Wait for at most
- TIMEOUT seconds, and use signal mask SIGMASK while waiting. A null
- pointer parameter stands for no descriptors, an infinite timeout,
- or an unaffected signal mask. */
- #if !HAVE_PSELECT
- int
- pselect (int nfds, fd_set *restrict rfds,
- fd_set *restrict wfds, fd_set *restrict xfds,
- struct timespec const *restrict timeout,
- sigset_t const *restrict sigmask)
- {
- int select_result;
- sigset_t origmask;
- struct timeval tv, *tvp;
- if (timeout)
- {
- if (! (0 <= timeout->tv_nsec && timeout->tv_nsec < 1000000000))
- {
- errno = EINVAL;
- return -1;
- }
- tv.tv_sec = timeout->tv_sec;
- tv.tv_usec = (timeout->tv_nsec + 999) / 1000;
- tvp = &tv;
- }
- else
- tvp = NULL;
- /* Signal mask munging should be atomic, but this is the best we can
- do in this emulation. */
- if (sigmask)
- pthread_sigmask (SIG_SETMASK, sigmask, &origmask);
- select_result = select (nfds, rfds, wfds, xfds, tvp);
- if (sigmask)
- {
- int select_errno = errno;
- pthread_sigmask (SIG_SETMASK, &origmask, NULL);
- errno = select_errno;
- }
- return select_result;
- }
- #else /* HAVE_PSELECT */
- # include <unistd.h>
- # undef pselect
- int
- rpl_pselect (int nfds, fd_set *restrict rfds,
- fd_set *restrict wfds, fd_set *restrict xfds,
- struct timespec const *restrict timeout,
- sigset_t const *restrict sigmask)
- {
- int i;
- /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
- if (nfds < 0 || nfds > FD_SETSIZE)
- {
- errno = EINVAL;
- return -1;
- }
- for (i = 0; i < nfds; i++)
- {
- if (((rfds && FD_ISSET (i, rfds))
- || (wfds && FD_ISSET (i, wfds))
- || (xfds && FD_ISSET (i, xfds)))
- && dup2 (i, i) != i)
- return -1;
- }
- return pselect (nfds, rfds, wfds, xfds, timeout, sigmask);
- }
- #endif
|