--- pth_high.c 2002/11/08 19:12:13 1.103
+++ pth_high.c 2002/11/08 20:26:02 1.104
@@ -461,18 +461,20 @@
INTERNALLY THE SCHEDULER IS ONLY select(2) BASED!! */
int pth_poll_ev(struct pollfd *pfd, nfds_t nfd, int timeout, pth_event_t ev_extra)
{
- fd_set rfds, wfds, efds;
+ fd_set rfds, wfds, efds, xfds;
struct timeval tv, *ptv;
- int maxfd, rc, ok;
+ int maxfd, rc, n;
unsigned int i;
char data[64];
pth_implicit_init();
pth_debug2("pth_poll_ev: called from thread \"%s\"", pth_current->name);
- /* poll(2) semantics */
+ /* argument sanity checks */
if (pfd == NULL)
return pth_error(-1, EFAULT);
+ if (nfd < 0 || nfd > FD_SETSIZE)
+ return pth_error(-1, EINVAL);
/* convert timeout number into a timeval structure */
ptv = &tv;
@@ -487,7 +489,7 @@
}
else if (timeout > 0) {
/* return after timeout */
- ptv->tv_sec = timeout / 1000;
+ ptv->tv_sec = (timeout / 1000);
ptv->tv_usec = (timeout % 1000) * 1000;
}
else
@@ -498,14 +500,19 @@
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
- for(i = 0; i < nfd; i++) {
- if (!pth_util_fd_valid(pfd[i].fd))
- return pth_error(-1, EBADF);
+ FD_ZERO(&xfds);
+ for (i = 0; i < nfd; i++) {
+ /* convert into fd_sets but remember that BSD select(2) says
+ "the only exceptional condition detectable is out-of-band
+ data received on a socket", hence we push POLLWRBAND events
+ onto wfds instead of efds. Additionally, remember invalid
+ filedescriptors in an extra fd_set xfds. */
+ if (!pth_util_fd_valid(pfd[i].fd)) {
+ FD_SET(pfd[i].fd, &xfds);
+ continue;
+ }
if (pfd[i].events & (POLLIN|POLLRDNORM))
FD_SET(pfd[i].fd, &rfds);
- /* see select(2): "the only exceptional condition detectable
- is out-of-band data received on a socket", hence we push
- POLLWRBAND events onto wfds instead of efds. */
if (pfd[i].events & (POLLOUT|POLLWRNORM|POLLWRBAND))
FD_SET(pfd[i].fd, &wfds);
if (pfd[i].events & (POLLPRI|POLLRDBAND))
@@ -516,60 +523,64 @@
POLLWRNORM|POLLWRBAND)))
maxfd = pfd[i].fd;
}
- if (maxfd == -1)
- return pth_error(-1, EINVAL);
- /* examine fd sets */
- rc = pth_select_ev(maxfd+1, &rfds, &wfds, &efds, ptv, ev_extra);
+ /* examine fd sets with pth_select(3) */
+ rc = -1;
+ if (maxfd != -1) {
+ rc = pth_select_ev(maxfd+1, &rfds, &wfds, &efds, ptv, ev_extra);
+ if (rc < 0)
+ return pth_error(-1, errno);
+ else if (rc == 0)
+ return 0;
+ }
- /* establish results */
- if (rc > 0) {
- rc = 0;
- for (i = 0; i < nfd; i++) {
- ok = 0;
- pfd[i].revents = 0;
- if (pfd[i].fd < 0) {
+ /* POSIX.1-2001/SUSv3 compliant result establishment */
+ n = 0;
+ for (i = 0; i < nfd; i++) {
+ pfd[i].revents = 0;
+ if (FD_ISSET(pfd[i].fd, &xfds)) {
+ if (pfd[i].fd >= 0) {
pfd[i].revents |= POLLNVAL;
- continue;
- }
- if (FD_ISSET(pfd[i].fd, &rfds)) {
- if (pfd[i].events & POLLIN)
- pfd[i].revents |= POLLIN;
- if (pfd[i].events & POLLRDNORM)
- pfd[i].revents |= POLLRDNORM;
- ok++;
- /* support for POLLHUP */
- if (recv(pfd[i].fd, data, sizeof(data), MSG_PEEK) == -1) {
- if ( errno == ESHUTDOWN || errno == ECONNRESET
- || errno == ECONNABORTED || errno == ENETRESET) {
- pfd[i].revents &= ~(POLLIN);
- pfd[i].revents &= ~(POLLRDNORM);
- pfd[i].revents |= POLLHUP;
- ok--;
- }
- }
+ n++;
}
- if (FD_ISSET(pfd[i].fd, &wfds)) {
- if (pfd[i].events & POLLOUT)
- pfd[i].revents |= POLLOUT;
- if (pfd[i].events & POLLWRNORM)
- pfd[i].revents |= POLLWRNORM;
- if (pfd[i].events & POLLWRBAND)
- pfd[i].revents |= POLLWRBAND;
- ok++;
- }
- if (FD_ISSET(pfd[i].fd, &efds)) {
- if (pfd[i].events & POLLPRI)
- pfd[i].revents |= POLLPRI;
- if (pfd[i].events & POLLRDBAND)
- pfd[i].revents |= POLLRDBAND;
- ok++;
+ continue;
+ }
+ if (maxfd == -1)
+ continue;
+ if (FD_ISSET(pfd[i].fd, &rfds)) {
+ if (pfd[i].events & POLLIN)
+ pfd[i].revents |= POLLIN;
+ if (pfd[i].events & POLLRDNORM)
+ pfd[i].revents |= POLLRDNORM;
+ n++;
+ /* support for POLLHUP */
+ if ( recv(pfd[i].fd, data, sizeof(data), MSG_PEEK) == -1
+ && ( errno == ESHUTDOWN || errno == ECONNRESET
+ || errno == ECONNABORTED || errno == ENETRESET )) {
+ pfd[i].revents &= ~(POLLIN);
+ pfd[i].revents &= ~(POLLRDNORM);
+ pfd[i].revents |= POLLHUP;
}
- if (ok)
- rc++;
+ }
+ else if (FD_ISSET(pfd[i].fd, &wfds)) {
+ if (pfd[i].events & POLLOUT)
+ pfd[i].revents |= POLLOUT;
+ if (pfd[i].events & POLLWRNORM)
+ pfd[i].revents |= POLLWRNORM;
+ if (pfd[i].events & POLLWRBAND)
+ pfd[i].revents |= POLLWRBAND;
+ n++;
+ }
+ else if (FD_ISSET(pfd[i].fd, &efds)) {
+ if (pfd[i].events & POLLPRI)
+ pfd[i].revents |= POLLPRI;
+ if (pfd[i].events & POLLRDBAND)
+ pfd[i].revents |= POLLRDBAND;
+ n++;
}
}
- return rc;
+
+ return n;
}
/* Pth variant of connect(2) */
|