Loading CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,10 @@ Yang Tse (27 March 2007) - Internal function Curl_select() renamed to Curl_socket_ready() New Internal wrapper function Curl_select() around select (2), it uses poll() when a fine poll() is available, so now libcurl can be built without select() support at all if a fine poll() is available. Daniel S (25 March 2007) - Daniel Johnson fixed multi code to traverse the easy handle list properly. A left-over bug from the February 21 fix. Loading RELEASE-NOTES +1 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ This release includes the following changes: o added experimental CURL_ACKNOWLEDGE_EINTR symbol definition check o --key and new --pubkey options for SSH public key file logins o --pass now works for a SSH public key file, too o select (2) support no longer needed to build the library if poll() used This release includes the following bugfixes: Loading lib/easy.c +2 −5 Original line number Diff line number Diff line Loading @@ -61,10 +61,6 @@ #include <sys/param.h> #endif #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif #endif /* WIN32 ... */ #include "urldata.h" Loading @@ -79,6 +75,7 @@ #include "memory.h" #include "progress.h" #include "easyif.h" #include "select.h" #include "sendf.h" /* for failf function prototype */ #include <ca-bundle.h> Loading Loading @@ -417,7 +414,7 @@ CURLcode curl_easy_perform(CURL *easy) /* get file descriptors from the transfers */ curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); if(rc == -1) /* select error */ Loading lib/hostares.c +4 −3 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ #include "url.h" #include "multiif.h" #include "connect.h" #include "select.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> Loading Loading @@ -144,7 +145,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn, nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds); (void)select(nfds, &read_fds, &write_fds, NULL, (void)Curl_select(nfds, &read_fds, &write_fds, NULL, (struct timeval *)&tv); /* Call ares_process() unconditonally here, even if we simply timed out Loading Loading @@ -210,7 +211,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, /* no file descriptors means we're done waiting */ break; tvp = ares_timeout(data->state.areschannel, &store, &tv); count = select(nfds, &read_fds, &write_fds, NULL, tvp); count = Curl_select(nfds, &read_fds, &write_fds, NULL, tvp); if ((count < 0) && (SOCKERRNO != EINVAL)) break; Loading lib/select.c +195 −2 Original line number Diff line number Diff line Loading @@ -32,8 +32,8 @@ #include <sys/time.h> #endif #ifndef HAVE_SELECT #error "We can't compile without select() support!" #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) #error "We can't compile without select() or poll() support." #endif #ifdef __BEOS__ Loading Loading @@ -64,6 +64,7 @@ #if defined(USE_WINSOCK) || defined(TPF) #define VERIFY_SOCK(x) do { } while (0) #define VERIFY_NFDS(x) do { } while (0) #else #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) #define VERIFY_SOCK(x) do { \ Loading @@ -72,6 +73,13 @@ return -1; \ } \ } while(0) #define VALID_NFDS(n) (((n) >= 0) && ((n) <= FD_SETSIZE)) #define VERIFY_NFDS(x) do { \ if(!VALID_NFDS(x)) { \ SET_SOCKERRNO(EINVAL); \ return -1; \ } \ } while(0) #endif /* Convenience local macros */ Loading @@ -84,6 +92,8 @@ #define error_not_EINTR (1) #endif #define SMALL_POLLNFDS 0X20 /* * Internal function used for waiting a specific amount of ms * in Curl_socket_ready() and Curl_poll() when no file descriptor Loading Loading @@ -424,6 +434,189 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) return r; } /* * This is a wrapper around select(). It uses poll() when a fine * poll() is available, in order to avoid limits with FD_SETSIZE, * otherwise select() is used. An error is returned if select() is * being used and a the number of file descriptors is larger than * FD_SETSIZE. A NULL timeout pointer makes this function wait * indefinitely, unles no valid file descriptor is given, when this * happens the NULL timeout is ignored and the function times out * immediately. When compiled with CURL_ACKNOWLEDGE_EINTR defined, * EINTR condition is honored and function might exit early without * awaiting timeout, otherwise EINTR will be ignored. * * Return values: * -1 = system call error or nfds > FD_SETSIZE * 0 = timeout * N = number of file descriptors kept in file descriptor sets. */ int Curl_select(int nfds, fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep, struct timeval *timeout) { struct timeval initial_tv; int timeout_ms; int pending_ms; int error; int r; #ifdef HAVE_POLL_FINE struct pollfd small_fds[SMALL_POLLNFDS]; struct pollfd *poll_fds; int ix; int fd; int poll_nfds = 0; #else struct timeval pending_tv; struct timeval *ptimeout; #endif int ret = 0; if ((nfds < 0) || ((nfds > 0) && (!fds_read && !fds_write && !fds_excep))) { SET_SOCKERRNO(EINVAL); return -1; } if (timeout) { if ((timeout->tv_sec < 0) || (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000)) { SET_SOCKERRNO(EINVAL); return -1; } timeout_ms = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); } else { timeout_ms = -1; } if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) { r = wait_ms(timeout_ms); return r; } pending_ms = timeout_ms; initial_tv = curlx_tvnow(); #ifdef HAVE_POLL_FINE if (fds_read || fds_write || fds_excep) { fd = nfds; while (fd--) { if ((fds_read && (0 != FD_ISSET(fd, fds_read))) || (fds_write && (0 != FD_ISSET(fd, fds_write))) || (fds_excep && (0 != FD_ISSET(fd, fds_excep)))) poll_nfds++; } } if (!poll_nfds) poll_fds = NULL; else if (poll_nfds <= SMALL_POLLNFDS) poll_fds = small_fds; else { poll_fds = calloc((size_t)poll_nfds, sizeof(struct pollfd)); if (!poll_fds) { SET_SOCKERRNO(ENOBUFS); return -1; } } if (poll_fds) { ix = 0; fd = nfds; while (fd--) { poll_fds[ix].events = 0; if (fds_read && (0 != FD_ISSET(fd, fds_read))) poll_fds[ix].events |= (POLLRDNORM|POLLIN); if (fds_write && (0 != FD_ISSET(fd, fds_write))) poll_fds[ix].events |= (POLLWRNORM|POLLOUT); if (fds_excep && (0 != FD_ISSET(fd, fds_excep))) poll_fds[ix].events |= (POLLRDBAND|POLLPRI); if (poll_fds[ix].events) { poll_fds[ix].fd = fd; poll_fds[ix].revents = 0; ix++; } } } do { if (timeout_ms < 0) pending_ms = -1; r = poll(poll_fds, poll_nfds, pending_ms); } while ((r == -1) && (error = SOCKERRNO) && (error != EINVAL) && error_not_EINTR && ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0))); if (r < 0) ret = -1; if (r > 0) { ix = poll_nfds; while (ix--) { if (poll_fds[ix].revents & POLLNVAL) { SET_SOCKERRNO(EBADF); ret = -1; break; } } } if (!ret) { ix = poll_nfds; while (ix--) { if (fds_read && (0 != FD_ISSET(poll_fds[ix].fd, fds_read))) { if (0 == (poll_fds[ix].revents & (POLLRDNORM|POLLERR|POLLHUP|POLLIN))) FD_CLR(poll_fds[ix].fd, fds_read); else ret++; } if (fds_write && (0 != FD_ISSET(poll_fds[ix].fd, fds_write))) { if (0 == (poll_fds[ix].revents & (POLLWRNORM|POLLERR|POLLHUP|POLLOUT))) FD_CLR(poll_fds[ix].fd, fds_write); else ret++; } if (fds_excep && (0 != FD_ISSET(poll_fds[ix].fd, fds_excep))) { if (0 == (poll_fds[ix].revents & (POLLRDBAND|POLLERR|POLLHUP|POLLPRI))) FD_CLR(poll_fds[ix].fd, fds_excep); else ret++; } } } if (poll_fds && (poll_nfds > SMALL_POLLNFDS)) free(poll_fds); #else /* HAVE_POLL_FINE */ VERIFY_NFDS(nfds); ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; do { if (ptimeout) { pending_tv.tv_sec = pending_ms / 1000; pending_tv.tv_usec = (pending_ms % 1000) * 1000; } r = select(nfds, fds_read, fds_write, fds_excep, ptimeout); } while ((r == -1) && (error = SOCKERRNO) && (error != EINVAL) && (error != EBADF) && error_not_EINTR && ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0))); if (r < 0) ret = -1; else ret = r; #endif /* HAVE_POLL_FINE */ return ret; } #ifdef TPF /* * This is a replacement for select() on the TPF platform. Loading Loading
CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,10 @@ Yang Tse (27 March 2007) - Internal function Curl_select() renamed to Curl_socket_ready() New Internal wrapper function Curl_select() around select (2), it uses poll() when a fine poll() is available, so now libcurl can be built without select() support at all if a fine poll() is available. Daniel S (25 March 2007) - Daniel Johnson fixed multi code to traverse the easy handle list properly. A left-over bug from the February 21 fix. Loading
RELEASE-NOTES +1 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ This release includes the following changes: o added experimental CURL_ACKNOWLEDGE_EINTR symbol definition check o --key and new --pubkey options for SSH public key file logins o --pass now works for a SSH public key file, too o select (2) support no longer needed to build the library if poll() used This release includes the following bugfixes: Loading
lib/easy.c +2 −5 Original line number Diff line number Diff line Loading @@ -61,10 +61,6 @@ #include <sys/param.h> #endif #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif #endif /* WIN32 ... */ #include "urldata.h" Loading @@ -79,6 +75,7 @@ #include "memory.h" #include "progress.h" #include "easyif.h" #include "select.h" #include "sendf.h" /* for failf function prototype */ #include <ca-bundle.h> Loading Loading @@ -417,7 +414,7 @@ CURLcode curl_easy_perform(CURL *easy) /* get file descriptors from the transfers */ curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); if(rc == -1) /* select error */ Loading
lib/hostares.c +4 −3 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ #include "url.h" #include "multiif.h" #include "connect.h" #include "select.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> Loading Loading @@ -144,7 +145,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn, nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds); (void)select(nfds, &read_fds, &write_fds, NULL, (void)Curl_select(nfds, &read_fds, &write_fds, NULL, (struct timeval *)&tv); /* Call ares_process() unconditonally here, even if we simply timed out Loading Loading @@ -210,7 +211,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, /* no file descriptors means we're done waiting */ break; tvp = ares_timeout(data->state.areschannel, &store, &tv); count = select(nfds, &read_fds, &write_fds, NULL, tvp); count = Curl_select(nfds, &read_fds, &write_fds, NULL, tvp); if ((count < 0) && (SOCKERRNO != EINVAL)) break; Loading
lib/select.c +195 −2 Original line number Diff line number Diff line Loading @@ -32,8 +32,8 @@ #include <sys/time.h> #endif #ifndef HAVE_SELECT #error "We can't compile without select() support!" #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) #error "We can't compile without select() or poll() support." #endif #ifdef __BEOS__ Loading Loading @@ -64,6 +64,7 @@ #if defined(USE_WINSOCK) || defined(TPF) #define VERIFY_SOCK(x) do { } while (0) #define VERIFY_NFDS(x) do { } while (0) #else #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) #define VERIFY_SOCK(x) do { \ Loading @@ -72,6 +73,13 @@ return -1; \ } \ } while(0) #define VALID_NFDS(n) (((n) >= 0) && ((n) <= FD_SETSIZE)) #define VERIFY_NFDS(x) do { \ if(!VALID_NFDS(x)) { \ SET_SOCKERRNO(EINVAL); \ return -1; \ } \ } while(0) #endif /* Convenience local macros */ Loading @@ -84,6 +92,8 @@ #define error_not_EINTR (1) #endif #define SMALL_POLLNFDS 0X20 /* * Internal function used for waiting a specific amount of ms * in Curl_socket_ready() and Curl_poll() when no file descriptor Loading Loading @@ -424,6 +434,189 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) return r; } /* * This is a wrapper around select(). It uses poll() when a fine * poll() is available, in order to avoid limits with FD_SETSIZE, * otherwise select() is used. An error is returned if select() is * being used and a the number of file descriptors is larger than * FD_SETSIZE. A NULL timeout pointer makes this function wait * indefinitely, unles no valid file descriptor is given, when this * happens the NULL timeout is ignored and the function times out * immediately. When compiled with CURL_ACKNOWLEDGE_EINTR defined, * EINTR condition is honored and function might exit early without * awaiting timeout, otherwise EINTR will be ignored. * * Return values: * -1 = system call error or nfds > FD_SETSIZE * 0 = timeout * N = number of file descriptors kept in file descriptor sets. */ int Curl_select(int nfds, fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep, struct timeval *timeout) { struct timeval initial_tv; int timeout_ms; int pending_ms; int error; int r; #ifdef HAVE_POLL_FINE struct pollfd small_fds[SMALL_POLLNFDS]; struct pollfd *poll_fds; int ix; int fd; int poll_nfds = 0; #else struct timeval pending_tv; struct timeval *ptimeout; #endif int ret = 0; if ((nfds < 0) || ((nfds > 0) && (!fds_read && !fds_write && !fds_excep))) { SET_SOCKERRNO(EINVAL); return -1; } if (timeout) { if ((timeout->tv_sec < 0) || (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000)) { SET_SOCKERRNO(EINVAL); return -1; } timeout_ms = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); } else { timeout_ms = -1; } if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) { r = wait_ms(timeout_ms); return r; } pending_ms = timeout_ms; initial_tv = curlx_tvnow(); #ifdef HAVE_POLL_FINE if (fds_read || fds_write || fds_excep) { fd = nfds; while (fd--) { if ((fds_read && (0 != FD_ISSET(fd, fds_read))) || (fds_write && (0 != FD_ISSET(fd, fds_write))) || (fds_excep && (0 != FD_ISSET(fd, fds_excep)))) poll_nfds++; } } if (!poll_nfds) poll_fds = NULL; else if (poll_nfds <= SMALL_POLLNFDS) poll_fds = small_fds; else { poll_fds = calloc((size_t)poll_nfds, sizeof(struct pollfd)); if (!poll_fds) { SET_SOCKERRNO(ENOBUFS); return -1; } } if (poll_fds) { ix = 0; fd = nfds; while (fd--) { poll_fds[ix].events = 0; if (fds_read && (0 != FD_ISSET(fd, fds_read))) poll_fds[ix].events |= (POLLRDNORM|POLLIN); if (fds_write && (0 != FD_ISSET(fd, fds_write))) poll_fds[ix].events |= (POLLWRNORM|POLLOUT); if (fds_excep && (0 != FD_ISSET(fd, fds_excep))) poll_fds[ix].events |= (POLLRDBAND|POLLPRI); if (poll_fds[ix].events) { poll_fds[ix].fd = fd; poll_fds[ix].revents = 0; ix++; } } } do { if (timeout_ms < 0) pending_ms = -1; r = poll(poll_fds, poll_nfds, pending_ms); } while ((r == -1) && (error = SOCKERRNO) && (error != EINVAL) && error_not_EINTR && ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0))); if (r < 0) ret = -1; if (r > 0) { ix = poll_nfds; while (ix--) { if (poll_fds[ix].revents & POLLNVAL) { SET_SOCKERRNO(EBADF); ret = -1; break; } } } if (!ret) { ix = poll_nfds; while (ix--) { if (fds_read && (0 != FD_ISSET(poll_fds[ix].fd, fds_read))) { if (0 == (poll_fds[ix].revents & (POLLRDNORM|POLLERR|POLLHUP|POLLIN))) FD_CLR(poll_fds[ix].fd, fds_read); else ret++; } if (fds_write && (0 != FD_ISSET(poll_fds[ix].fd, fds_write))) { if (0 == (poll_fds[ix].revents & (POLLWRNORM|POLLERR|POLLHUP|POLLOUT))) FD_CLR(poll_fds[ix].fd, fds_write); else ret++; } if (fds_excep && (0 != FD_ISSET(poll_fds[ix].fd, fds_excep))) { if (0 == (poll_fds[ix].revents & (POLLRDBAND|POLLERR|POLLHUP|POLLPRI))) FD_CLR(poll_fds[ix].fd, fds_excep); else ret++; } } } if (poll_fds && (poll_nfds > SMALL_POLLNFDS)) free(poll_fds); #else /* HAVE_POLL_FINE */ VERIFY_NFDS(nfds); ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; do { if (ptimeout) { pending_tv.tv_sec = pending_ms / 1000; pending_tv.tv_usec = (pending_ms % 1000) * 1000; } r = select(nfds, fds_read, fds_write, fds_excep, ptimeout); } while ((r == -1) && (error = SOCKERRNO) && (error != EINVAL) && (error != EBADF) && error_not_EINTR && ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0))); if (r < 0) ret = -1; else ret = r; #endif /* HAVE_POLL_FINE */ return ret; } #ifdef TPF /* * This is a replacement for select() on the TPF platform. Loading