diff options
Diffstat (limited to 'lib/select.c')
-rw-r--r-- | lib/select.c | 177 |
1 files changed, 52 insertions, 125 deletions
diff --git a/lib/select.c b/lib/select.c index abb124a..7d1f944 100644 --- a/lib/select.c +++ b/lib/select.c @@ -9,7 +9,7 @@ * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms - * are also available at https://curl.haxx.se/docs/copyright.html. + * are also available at https://curl.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is @@ -149,15 +149,14 @@ int Curl_select(curl_socket_t maxfd, /* highest socket number */ { struct timeval pending_tv; struct timeval *ptimeout; - int r; #ifdef USE_WINSOCK /* WinSock select() can't handle zero events. See the comment below. */ if((!fds_read || fds_read->fd_count == 0) && (!fds_write || fds_write->fd_count == 0) && (!fds_err || fds_err->fd_count == 0)) { - r = Curl_wait_ms(timeout_ms); - return r; + /* no sockets, just wait */ + return Curl_wait_ms(timeout_ms); } #endif @@ -209,17 +208,16 @@ int Curl_select(curl_socket_t maxfd, /* highest socket number */ descriptor set must contain at least one handle to a socket. It is unclear why WinSock doesn't just handle this for us instead of - calling this an error. + calling this an error. Luckily, with WinSock, we can _also_ ask how + many bits are set on an fd_set. So, let's just check it beforehand. */ - r = select((int)maxfd + 1, - fds_read && fds_read->fd_count ? fds_read : NULL, - fds_write && fds_write->fd_count ? fds_write : NULL, - fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout); + return select((int)maxfd + 1, + fds_read && fds_read->fd_count ? fds_read : NULL, + fds_write && fds_write->fd_count ? fds_write : NULL, + fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout); #else - r = select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout); + return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout); #endif - - return r; } /* @@ -247,23 +245,14 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ curl_socket_t writefd, /* socket to write to */ timediff_t timeout_ms) /* milliseconds to wait */ { -#ifdef HAVE_POLL_FINE struct pollfd pfd[3]; int num; -#else - fd_set fds_read; - fd_set fds_write; - fd_set fds_err; - curl_socket_t maxfd; -#endif int r; - int ret; if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) { /* no sockets, just wait */ - r = Curl_wait_ms(timeout_ms); - return r; + return Curl_wait_ms(timeout_ms); } /* Avoid initial timestamp, avoid Curl_now() call, when elapsed @@ -271,8 +260,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ when function is called with a zero timeout or a negative timeout value indicating a blocking call should be performed. */ -#ifdef HAVE_POLL_FINE - num = 0; if(readfd0 != CURL_SOCKET_BAD) { pfd[num].fd = readfd0; @@ -288,7 +275,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ } if(writefd != CURL_SOCKET_BAD) { pfd[num].fd = writefd; - pfd[num].events = POLLWRNORM|POLLOUT; + pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI; pfd[num].revents = 0; num++; } @@ -297,101 +284,30 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ if(r <= 0) return r; - ret = 0; + r = 0; num = 0; if(readfd0 != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) - ret |= CURL_CSELECT_IN; + r |= CURL_CSELECT_IN; if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) - ret |= CURL_CSELECT_ERR; + r |= CURL_CSELECT_ERR; num++; } if(readfd1 != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) - ret |= CURL_CSELECT_IN2; + r |= CURL_CSELECT_IN2; if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) - ret |= CURL_CSELECT_ERR; + r |= CURL_CSELECT_ERR; num++; } if(writefd != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLWRNORM|POLLOUT)) - ret |= CURL_CSELECT_OUT; - if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL)) - ret |= CURL_CSELECT_ERR; - } - - return ret; - -#else /* HAVE_POLL_FINE */ - - FD_ZERO(&fds_err); - maxfd = (curl_socket_t)-1; - - FD_ZERO(&fds_read); - if(readfd0 != CURL_SOCKET_BAD) { - VERIFY_SOCK(readfd0); - FD_SET(readfd0, &fds_read); - FD_SET(readfd0, &fds_err); - maxfd = readfd0; - } - if(readfd1 != CURL_SOCKET_BAD) { - VERIFY_SOCK(readfd1); - FD_SET(readfd1, &fds_read); - FD_SET(readfd1, &fds_err); - if(readfd1 > maxfd) - maxfd = readfd1; - } - - FD_ZERO(&fds_write); - if(writefd != CURL_SOCKET_BAD) { - VERIFY_SOCK(writefd); - FD_SET(writefd, &fds_write); - FD_SET(writefd, &fds_err); - if(writefd > maxfd) - maxfd = writefd; - } - - /* We know that we have at least one bit set in at least two fd_sets in - this case, but we may have no bits set in either fds_read or fd_write, - so check for that and handle it. Luckily, with WinSock, we can _also_ - ask how many bits are set on an fd_set. - - Note also that WinSock ignores the first argument, so we don't worry - about the fact that maxfd is computed incorrectly with WinSock (since - curl_socket_t is unsigned in such cases and thus -1 is the largest - value). - */ - r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); - - if(r < 0) - return -1; - if(r == 0) - return 0; - - ret = 0; - if(readfd0 != CURL_SOCKET_BAD) { - if(FD_ISSET(readfd0, &fds_read)) - ret |= CURL_CSELECT_IN; - if(FD_ISSET(readfd0, &fds_err)) - ret |= CURL_CSELECT_ERR; - } - if(readfd1 != CURL_SOCKET_BAD) { - if(FD_ISSET(readfd1, &fds_read)) - ret |= CURL_CSELECT_IN2; - if(FD_ISSET(readfd1, &fds_err)) - ret |= CURL_CSELECT_ERR; - } - if(writefd != CURL_SOCKET_BAD) { - if(FD_ISSET(writefd, &fds_write)) - ret |= CURL_CSELECT_OUT; - if(FD_ISSET(writefd, &fds_err)) - ret |= CURL_CSELECT_ERR; + r |= CURL_CSELECT_OUT; + if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) + r |= CURL_CSELECT_ERR; } - return ret; - -#endif /* HAVE_POLL_FINE */ - + return r; } /* @@ -431,8 +347,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) } if(fds_none) { /* no sockets, just wait */ - r = Curl_wait_ms(timeout_ms); - return r; + return Curl_wait_ms(timeout_ms); } /* Avoid initial timestamp, avoid Curl_now() call, when elapsed @@ -454,11 +369,8 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) else pending_ms = 0; r = poll(ufds, nfds, pending_ms); - - if(r < 0) - return -1; - if(r == 0) - return 0; + if(r <= 0) + return r; for(i = 0; i < nfds; i++) { if(ufds[i].fd == CURL_SOCKET_BAD) @@ -466,7 +378,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) if(ufds[i].revents & POLLHUP) ufds[i].revents |= POLLIN; if(ufds[i].revents & POLLERR) - ufds[i].revents |= (POLLIN|POLLOUT); + ufds[i].revents |= POLLIN|POLLOUT; } #else /* HAVE_POLL_FINE */ @@ -482,7 +394,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) continue; VERIFY_SOCK(ufds[i].fd); if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| - POLLRDNORM|POLLWRNORM|POLLRDBAND)) { + POLLRDNORM|POLLWRNORM|POLLRDBAND)) { if(ufds[i].fd > maxfd) maxfd = ufds[i].fd; if(ufds[i].events & (POLLRDNORM|POLLIN)) @@ -494,24 +406,39 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) } } + /* + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); - - if(r < 0) - return -1; - if(r == 0) - return 0; + if(r <= 0) + return r; r = 0; for(i = 0; i < nfds; i++) { ufds[i].revents = 0; if(ufds[i].fd == CURL_SOCKET_BAD) continue; - if(FD_ISSET(ufds[i].fd, &fds_read)) - ufds[i].revents |= POLLIN; - if(FD_ISSET(ufds[i].fd, &fds_write)) - ufds[i].revents |= POLLOUT; - if(FD_ISSET(ufds[i].fd, &fds_err)) - ufds[i].revents |= POLLPRI; + if(FD_ISSET(ufds[i].fd, &fds_read)) { + if(ufds[i].events & POLLRDNORM) + ufds[i].revents |= POLLRDNORM; + if(ufds[i].events & POLLIN) + ufds[i].revents |= POLLIN; + } + if(FD_ISSET(ufds[i].fd, &fds_write)) { + if(ufds[i].events & POLLWRNORM) + ufds[i].revents |= POLLWRNORM; + if(ufds[i].events & POLLOUT) + ufds[i].revents |= POLLOUT; + } + if(FD_ISSET(ufds[i].fd, &fds_err)) { + if(ufds[i].events & POLLRDBAND) + ufds[i].revents |= POLLRDBAND; + if(ufds[i].events & POLLPRI) + ufds[i].revents |= POLLPRI; + } if(ufds[i].revents != 0) r++; } |