Avoid assuming layout of fd_set

POSIX doesn't specify the internal layout of the fd_set object, so let's
not assume it is just a bit mask. This increases compatibility with
systems that have a different layout.

The assumption is also worthless as we already refuse to use file
descriptors over FD_SETSIZE anyway. Meaning that the default size of
fd_set is quite sufficient.
This commit is contained in:
Pierre Ossman 2022-07-06 13:52:10 +02:00 committed by Darren Tucker
parent 419aa8a312
commit d9df5689c2
No known key found for this signature in database
1 changed files with 12 additions and 26 deletions

View File

@ -47,9 +47,8 @@ ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmoutp,
const sigset_t *sigmask) const sigset_t *sigmask)
{ {
nfds_t i; nfds_t i;
int saved_errno, ret, fd, maxfd = 0; int ret, fd, maxfd = 0;
fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL; fd_set readfds, writefds, exceptfds;
size_t nmemb;
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
fd = fds[i].fd; fd = fds[i].fd;
@ -60,30 +59,23 @@ ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmoutp,
maxfd = MAX(maxfd, fd); maxfd = MAX(maxfd, fd);
} }
nmemb = howmany(maxfd + 1 , NFDBITS);
if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
(writefds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
(exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) {
saved_errno = ENOMEM;
ret = -1;
goto out;
}
/* populate event bit vectors for the events we're interested in */ /* populate event bit vectors for the events we're interested in */
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
fd = fds[i].fd; fd = fds[i].fd;
if (fd == -1) if (fd == -1)
continue; continue;
if (fds[i].events & POLLIN) if (fds[i].events & POLLIN)
FD_SET(fd, readfds); FD_SET(fd, &readfds);
if (fds[i].events & POLLOUT) if (fds[i].events & POLLOUT)
FD_SET(fd, writefds); FD_SET(fd, &writefds);
if (fds[i].events & POLLPRI) if (fds[i].events & POLLPRI)
FD_SET(fd, exceptfds); FD_SET(fd, &exceptfds);
} }
ret = pselect(maxfd + 1, readfds, writefds, exceptfds, tmoutp, sigmask); ret = pselect(maxfd + 1, &readfds, &writefds, &exceptfds, tmoutp, sigmask);
saved_errno = errno;
/* scan through select results and set poll() flags */ /* scan through select results and set poll() flags */
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
@ -91,20 +83,14 @@ ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmoutp,
fds[i].revents = 0; fds[i].revents = 0;
if (fd == -1) if (fd == -1)
continue; continue;
if ((fds[i].events & POLLIN) && FD_ISSET(fd, readfds)) if ((fds[i].events & POLLIN) && FD_ISSET(fd, &readfds))
fds[i].revents |= POLLIN; fds[i].revents |= POLLIN;
if ((fds[i].events & POLLOUT) && FD_ISSET(fd, writefds)) if ((fds[i].events & POLLOUT) && FD_ISSET(fd, &writefds))
fds[i].revents |= POLLOUT; fds[i].revents |= POLLOUT;
if ((fds[i].events & POLLPRI) && FD_ISSET(fd, exceptfds)) if ((fds[i].events & POLLPRI) && FD_ISSET(fd, &exceptfds))
fds[i].revents |= POLLPRI; fds[i].revents |= POLLPRI;
} }
out:
free(readfds);
free(writefds);
free(exceptfds);
if (ret == -1)
errno = saved_errno;
return ret; return ret;
} }
#endif /* !HAVE_PPOLL || BROKEN_POLL */ #endif /* !HAVE_PPOLL || BROKEN_POLL */