Index: ossp-pkg/pth/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/pth/ChangeLog,v rcsdiff -q -kk '-r1.596' '-r1.597' -u '/v/ossp/cvs/ossp-pkg/pth/ChangeLog,v' 2>/dev/null --- ChangeLog 2002/11/08 19:12:13 1.596 +++ ChangeLog 2002/11/08 20:26:02 1.597 @@ -21,7 +21,10 @@ Changes between 2.0b0 and 2.0b1 (07-Nov-2002 to xx-Nov-2002) - *) Make pth_select(2) more compliant to POSIX.1-2001/SUSv3 select(2). + *) Make pth_poll(3) more compliant to POSIX.1-2001/SUSv3 poll(2). + [Ralf S. Engelschall, Nick Hudson ] + + *) Make pth_select(3) more compliant to POSIX.1-2001/SUSv3 select(2). This especially fixes the polling-only situation (timeout = (0,0)). [Ralf S. Engelschall] Index: ossp-pkg/pth/pth_high.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_high.c,v rcsdiff -q -kk '-r1.103' '-r1.104' -u '/v/ossp/cvs/ossp-pkg/pth/pth_high.c,v' 2>/dev/null --- 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) */